Page 1 of 2
Force Save As Dialog box on mp3 download
Posted: Tue Mar 15, 2005 3:06 pm
by suspire
Whats up guys.
We're trying to put up a free download and need the file to save to peoples desktop instead of going into quicktime or whatever player is setup in their browser. I've got the code to do it via Content-Disposition but, can't get it to work.
Code: Select all
<?php
$file = 'http://brashmusic.com/download/Taylor_Hollingsworth-How_Could_You_Be_So_Cold.mp3';
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header('Content-Length: ' . filesize($filename));
header('Content-Disposition: attachment; filename=' . basename($file));
readfile($file);
?>
Here is the link on our server:
http://brashmusic.com/download/download3.php
And the error I get:
Parse error: parse error, unexpected T_VARIABLE in /home/brashmu/public_html/download/download.php on line 1
Anybody know what the problem is?
Thanks.
feyd | Please use Code: Select all
tags where approriate when posting code. Read: [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url][/color]
Posted: Tue Mar 15, 2005 3:11 pm
by Chris Corbyn
This is the only code in your file? As in <?php is line 1 itself?

Posted: Tue Mar 15, 2005 3:21 pm
by suspire
Indeed.
Am I missing something?
Posted: Tue Mar 15, 2005 3:24 pm
by feyd
did you write this in DreamWeaver by chance?
Sidenote: $filename != $file

Posted: Tue Mar 15, 2005 3:30 pm
by hongco
...also, you need to change the first line to the path to the file, not the url
Code: Select all
$file = 'http://brashmusic.com/download/Taylor_Hollingsworth-How_Could_You_Be_So_Cold.mp3';
// should've been something like, for instance, on linux:
$file = '/home/youraccount/public_html/download/yourfile.mp3';
Posted: Tue Mar 15, 2005 3:30 pm
by suspire
BBEdit.
Because its calling it from the same directory and doesn't like absolute urls?
download3.php and the mp3 are in the same dir.
Posted: Tue Mar 15, 2005 3:33 pm
by feyd
you may have, for whatever reason, an "invisible" character that may be causing it. If you retype the code (not copying it) into a new page/document/whatever, does it fix the problem?
Posted: Tue Mar 15, 2005 3:45 pm
by suspire
gave it a retype, same error:
http://www.brashmusic.com/download/download4.php
Code: Select all
<?php
$file = "http://brashmusic.com/download/Taylor_Hollingsworth-How_Could_You_Be_So_Cold.mp3";
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header('Content-Length: ' . filesize($filename));
header('Content-Disposition: attachment; filename=' . basename($file));
readfile($file);
?>
Posted: Tue Mar 15, 2005 3:49 pm
by suspire
Got it. Thanks guys.
Code: Select all
<?php
$file = "http://www.brashmusic.com/download/Taylor_Hollingsworth-How_Could_You_Be_So_Cold.mp3";
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$file\"");
header("Content-Description: File Transfert");
readfile($file);
?>
feyd | Please use Code: Select all
tags where approriate when posting code. Read: [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url][/color]
Posted: Tue Mar 15, 2005 3:50 pm
by hongco
suspire wrote:BBEdit.
Because its calling it from the same directory and doesn't like absolute urls?
download3.php and the mp3 are in the same dir.
my bad, the abs url is fine
Posted: Tue Mar 15, 2005 3:52 pm
by hongco
suspire wrote:gave it a retype, same error:
http://www.brashmusic.com/download/download4.php
Code: Select all
<?php
$file = "http://brashmusic.com/download/Taylor_Hollingsworth-How_Could_You_Be_So_Cold.mp3";
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header('Content-Length: ' . filesize($filename));
header('Content-Disposition: attachment; filename=' . basename($file));
readfile($file);
?>
change filesize($filename) to filesize($file) and you should be fine
Posted: Tue Mar 15, 2005 3:53 pm
by feyd
filesize() will make the server download a remote file to check the size. I'd seriously suggest using a local path to the file if possible.
Posted: Tue Mar 15, 2005 4:52 pm
by suspire
Thanks to David Molamphy for the final code edits:
Here's a more user-friendly, revised version:
Code: Select all
<?php
$path = "http://www.yourdomain.com/directory/";
$filename = $path . $_GET['file'];
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$file\"");
header("Content-Description: File Transfert");
readfile($file);
?>
Now, all you have to do when you want to download a file, is make sure the file name is attached to the URL. You can even do this through $_POST if you don't want people to know where the file resides. So...your link will look something like:
<a href="downlad_test.php?file=myfilename.mp3">Download Me</a>
Alrighty. Hope that helps.
David Molampny
http://molanphydesign.com
Posted: Tue Mar 15, 2005 5:11 pm
by Ambush Commander
Err... that code is really asking for some sort of cracker to exploit it. No input validation at all! GASP!
download.php?file=../forbidden/secretinfo.txt
is one way of exploiting it: they can access any file on your server using this script. GASP!
Well, actually, they're only allowed to access what a PHP script would be allowed to access... but that's still a lot!
Here's a revised version:
Code: Select all
<?php
$path = "http://www.yourdomain.com/directory/";
$filename = basename($_GET['file']);
$file = $path . $filename;
if (!file_exists($file) OR !is_readable($file)) {
echo "File doesn't exist or is unreadable!";
exit;
}
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$file\"");
header("Content-Description: File Transfer");
readfile($file);
?>
If possible, limit what can be inside the filename to, say, alphabetical characters and numbers, and only mp3 files, so this regexp:
Code: Select all
$exp = 'i/^ї0-9a-z]+.mp3$/';
Can be used to validate.
Hmm... It just occured to me: http://www.elouai.com/force-download.php was sitting around in my bookmarks. I don't know why I didn't share it with you earlier!
Posted: Tue Mar 15, 2005 5:26 pm
by feyd
psst.. $filename vs $file
It's also a good idea to validate that the file, at least exists and is readable by php.
