简体   繁体   中英

Dynamic file names with Apache mod_header and file downloads using Content-Disposition

I have a bad problem on my site where my file downloads are getting truncated when I use PHP to set the Content-Disposition to "attachment" and then sending the file using readfile() . I know this is somewhat of a notorious problem since there is plenty of discussion about it on PHP's readfile() manual page. I have tried each of the solutions posted there with no luck (sending chunked output, disabling gzip compression in both Apache/PHP). Here is the gist of that code, without all the workarounds, just as you'd find it on the PHP manual:

$file = '/path/to/ugly.file.name.mp4';
$filename = 'ANiceFileName.mp4';
header('Content-Description: File Transfer');
header('Content-Type: video/mp4');
header('Content-Disposition: attachment; filename='.$filename.'.mp4');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);

Most importantly, notice that I'd like to be able to send a dynamic file name to the browser, to avoid the more machine-friendly codes I use to store the files on disk. And yes, I have done plenty of security checks before this bit of code executes -- I already know readfile() can be a security flaw. :-)

The only reliable way I have found to send a complete file is to simply trash PHP and instead use Apache's mod_header to force the file as a download. Like so:

<FilesMatch "\.mp4$">
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</FilesMatch>

This works very well, but there's a big problem -- I can no longer generate dynamic file names upon request, which is somewhat important to my content. I already know about specifying ;filename=file_name.mp4 , but remember - I need to specify a dynamic name rather than just file_name.mp4 .

It would be really nice if I could somehow notify Apache (using PHP) of the dynamic file name when sending a file. Is that possible? Or am I going to be forced to rename all my files on disk to a user-friendly name? The PHP solutions just aren't working at all. My files are sometimes up to 15MB, and those are often truncated to less than 2MB when transferring. Ouch!

Help me Stack Overflow Kenobi! You're my only hope.

Is it getting truncated because the php script times out? set_time_limit?

Try mod_xsendfile as described here . This basically allows PHP to step out of the middle of the HTTP conversation at the point that PHP sets the X-Sendfile header - but, as you can see on that blog, it allows for setting your Content-Disposition header.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM