Force Save As Dialog box on mp3 download

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

suspire
Forum Newbie
Posts: 6
Joined: Tue Mar 15, 2005 2:54 pm

Force Save As Dialog box on mp3 download

Post 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

and

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]
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

This is the only code in your file? As in <?php is line 1 itself? :?
suspire
Forum Newbie
Posts: 6
Joined: Tue Mar 15, 2005 2:54 pm

Post by suspire »

Indeed.
Am I missing something?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

did you write this in DreamWeaver by chance?

Sidenote: $filename != $file ;)
hongco
Forum Contributor
Posts: 186
Joined: Sun Feb 20, 2005 2:49 pm

Post 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';
suspire
Forum Newbie
Posts: 6
Joined: Tue Mar 15, 2005 2:54 pm

Post 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.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post 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?
suspire
Forum Newbie
Posts: 6
Joined: Tue Mar 15, 2005 2:54 pm

Post 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);
?>
suspire
Forum Newbie
Posts: 6
Joined: Tue Mar 15, 2005 2:54 pm

Post 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

and

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]
hongco
Forum Contributor
Posts: 186
Joined: Sun Feb 20, 2005 2:49 pm

Post 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
hongco
Forum Contributor
Posts: 186
Joined: Sun Feb 20, 2005 2:49 pm

Post 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
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post 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.
suspire
Forum Newbie
Posts: 6
Joined: Tue Mar 15, 2005 2:54 pm

Post 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
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post 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/^&#1111;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! :twisted:
Last edited by Ambush Commander on Tue Mar 15, 2005 5:32 pm, edited 1 time in total.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post 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. :)
Post Reply