Web Hosting Talk







View Full Version : How do you prompt "File Save as" ? without using "document.execCommand"


latheesan
07-31-2005, 11:53 AM
Im created a file called d.php which takes the file name i am about to download and forwards it to a agreement page.

So, an example of downloading the file called dog.mp3 will be

http://www.mysite.com/d.php?file=dog.mp3

this request goes to a page called agree.php where on that page, it shows file's details like file name, size and last modified date and on the middle it has a little agreement box and at the very end it has the link to download the file.

this is the link part (the main problem i am having)

<td height="20" width="400" class="download">
<a href="[FILENAME]">[FILENAME]</a>
</td>

as you can see, the [FILENAME] is a macro that turns into a hyperlink like http://www.mysite.com/downloads/dog.mp3

the problem is, when ever i click on the link to download the file, it opens my windows media player and the video gets streamed, also people can leech off my site.

I tried using this method:

<a href="#" onclick="javascript:document.execCommand('SaveAs','1','[FILENAME]')">Click to save</a>

That method failed because it saves all the files in .htm or .html or .txt format for some reason

as you can see, im veryyy stuck :(

any possible ideas on how to over come this force downloading problem?

zoldar
07-31-2005, 01:33 PM
It seems, that there's no one sure and good solution ( see http://www.htmlhelp.com/faq/html/all.html#force-download ).

The href would point to a php script:

<a href="file.php?file=[FILENAME]">Click to save</a>

And the file.php itself could conatin ie. :

<?php

header("Content-type: application/x-file-to-save");
header("Content-Disposition: attachment; filename=".$_REQUEST['file']);
readfile($_REQUEST['file']);

?>

latheesan
07-31-2005, 01:35 PM
Wow, your code looks very promising, im going to try it immediately :)

zoldar
07-31-2005, 01:51 PM
Pay your attention to the fact that this piece of code may be potentially insecure. Ie. somebody could invoke it like that:

http://www.mysite.com/file.php?file=/etc/passwd

One way of dealing with that is to configure php properly (safe_mode = On first - it prevents user from reading the file that he doesn't own).

Other one would be checking passed filename against some list of valid filenames (invoked by dir() command in proper dir, held in db or whatever.

These are not the only ways of securing it - maybe somebody has some better idea... ?

zoldar
07-31-2005, 02:05 PM
Another one small correction to the code:

<?php

header("Content-type: application/x-file-to-save");
header("Content-Disposition: attachment; filename=".basename($_REQUEST['file']));
readfile($_REQUEST['file']);

?>

so that it wouldn't pass the whole path to the file as a filename.

latheesan
07-31-2005, 03:08 PM
erm where would i have to place the above code in my d.php file?


<?

$filedirectory = 'http://localhost/site.com/mp3s';

$filepath = 'root\site.com\mp3s';

$template = 'agree.php';

if (!$file){
header("Location: http://localhost/site.com/index.php?id=InvalidRequest");
exit();
}else

if ( !file_exists("$filepath/$file") ){
header("Location: http://localhost/site.com/index.php?id=FileNotFound");
exit();
}else

$fp = fopen ("$template", "r") or die_nice("Could not open template file: $template");
$contents = fread ($fp, filesize ($template));
fclose ($fp);

$contents = str_replace("[FILENAME]", $file, $contents);
$contents = str_replace("[FILESIZE]", number_format(filesize("$filepath/$file")), $contents);
$contents = str_replace("[MODIFIEDDATE]", date("F j Y", filemtime("$filepath/$file")), $contents);
$contents = str_replace("[DOWNLOAD]", "${filedirectory}/$file", $contents);

print stripslashes($contents);

?>

zoldar
07-31-2005, 04:37 PM
You've to change agree.php content. Can you put it here on the forum ?

Dan L
07-31-2005, 04:49 PM
Try meta redirecting to the file.

latheesan
07-31-2005, 05:19 PM
zoldar, i PM'ed you the simple version of the agree.php file

here it is again with the css and so on

latheesan
07-31-2005, 05:21 PM
Thanks for you PM

I got your new solution, im going to try it immediately :D

Thanks once again

latheesan
07-31-2005, 05:26 PM
Hey zoldar,

I didn what you asked me to do in the PM,

I placed your header script on the top agree.php and made the hyperlink like this

<a href="d.php?file=[FILENAME]">[FILENAME]</a>

and when i entered to try a download, i entered the url

http://www.site.com/d.php?file=song.mp3

it took me to the agree.php file, and then clicked on the hyperlink, then it just refreshed the page

so i was curious and right clicked on the link it created dynamically and see whats the url and it was this

http://www.site.com/d.php?file=song.mp3

Maybe this is why the page is keep refreshing, :bawling: how do i fix this now?

zoldar
07-31-2005, 05:35 PM
Ok once again...

Keep file d.php UNCHANGED - i mean in the state it was before all the changes.

Change the agree.php as I have shown you in PM - EXACTLY like it was written

Then ADD file.php in the same directory where dl.php and agree.php scripts reside with following content:


<?php

header("Content-type: application/x-file-to-save");
header("Content-Disposition: attachment; filename=".basename($_REQUEST['file']));
readfile($_REQUEST['file']);

?>

latheesan
07-31-2005, 06:01 PM
Hey thank zoldar,

Your suggestion worked great :D

ur da best man.

I'll be using this script to serve mp3 files only, at the moment the script is set to

Content-type: application/octetstream

what is the aplication type name thingy for MP3s?

zoldar
07-31-2005, 06:07 PM
Mime-type (Content-type) is audio/mpeg
However don't set it to that, because then it will be treated with default action on the client side (opened in player in most cases) - and it was that, what you have wanted to avoid, haven't you. Setting these content related headers to something other does the trick.

gilbert
07-31-2005, 06:10 PM
wow that looks like some neat stuff to do with php, good luck guys -gilbert

latheesan
07-31-2005, 06:15 PM
Setting these content related headers to something other does the trick

Good idea indeed, so i set the header to the these format:

header("Content-type: audio/x-midi");

and i atempted to download a file through the d.php?file=nerd.mp3 and this is what happened (look at the attachement) :(

so i changed back to audio/mpeg and tried that as well, i keep getting that same file size and it wont download properly

the orginal file size is about 5mb, but through the script when i download, its about 223 byes EVERYTIME

why is it doing this?

zoldar
07-31-2005, 06:20 PM
By 'something other' I mean something COMPLETELY other than any known media mime-type - like 'application/x-i-like-donuts' or 'application/x-whatever-else-you-want-to-put-here'

... and I hate donuts

latheesan
07-31-2005, 06:24 PM
lolz, me too

latheesan
07-31-2005, 06:28 PM
well, i changed the mime type to

"application/x-i-like-pie" lolz

but it stills downloads the files as 223 bytes wrongly

:( why???

zoldar
07-31-2005, 06:34 PM
Try changing it to application/octet-stream and see if it behaves the same

latheesan
07-31-2005, 06:36 PM
I changed it to "application/octet-stream" and it still downloading the file wrongly at 223 bytes :(

latheesan
07-31-2005, 07:57 PM
Hey guys, Zoldar helped me fix it. Thank man, great work :D