0

我正在提供一个 .mp3 文件(作为下载对话框,最终用户可以在其中重命名和保存文件)。论坛上有很多相互矛盾的建议,甚至在 php 手册的评论中也是如此。

我希望解决我的问题并在此处创建有关如何最好地执行此目标的参考:即,通过开始 php 编码器以最有效的方式开始提供可下载文件,可以使用清晰的“最佳实践摘要”。

如果您检查此处的代码并提出更正建议,我将不胜感激——这是帮助艺术家自行出版音乐、书籍等的网站的一部分。

为了测试,我将它作为 index.php 上传到我的服务器;也许这也是问题的一部分。

这个脚本的当前状态是浏览器挂了一点,然后将二进制文件作为文本加载到浏览器显示窗口中。

我在很多时候都认为我的问题是重要的“Content-Length”标头中的语法,或者我的标头的顺序,所以我尝试了所有这些的几个版本,但没有一个会中断下载。

这是我现在自己尝试的确切代码,
其中 ####### 表示 7 个数字(以字节为单位的实际文件大小),其他一切都应该清楚:

<?php
header('Server: ');
header('X-Powered-By: ');
header('Cache-Control: no-cache');
header('Expires: -1');
header('Content-Description: File Transfer');
header('Content-Transfer-Encoding: binary');
header('Content-Type: audio/mpeg');
header('Content-Disposition: attachment;filename="suggested-save-name.mp3"');  
header('Content-Length: #######["exact-file-name.mp3"]');
@readfile("http://full-public-url.com/exact-file-name.mp3"); 
ob_clean();
flush();
exit;
?>

返回这些响应标头:

>X-Powered-By:PHP/5.4.xy
>Vary:negotiate
>Transfer-Encoding:chunked
>TCN:choice
>Server:Apache
>Keep-Alive:timeout=2, max=200
>Date:Fri, 10 May 2013 16:mm:ss GMT
>Content-Type:text/html
>Content-Location:filename.php
>Connection:Keep-Alive

我希望这是我的脚本语法中的一个简单错误(或多个错误),或者我创建和保存 .php 文件的方式。我已验证设置为默认设置,php 是最新的,并且没有 .htaccess 问题。我已经仔细确保这个文件的末尾没有多余的空格,以及 web 目录中的所有其他文件,并且我已经尝试了带有和不带有关闭的脚本?>

先感谢您 ...


阅读答案后的最佳脚本,如下:

<?php
$file-variable=('./exact-file-name.mp3')
$size=filesize($file-variable);
header('Server: ');
header('X-Powered-By: ');
header('Cache-Control: no-cache');
header('Expires: -1');
header('Content-Type: application/octet-stream'); //will need to redirect for older IE
header('Content-Disposition: attachment; filename="suggested-save-name.mp3"');  
header('Content-Length: "$size"');
@readfile("$file-variable");
ob_clean();
flush();
exit;

成功的响应标头,来自更好的脚本(在删除 UTF-8 BOM 之后):

>Vary:negotiate
>TCN:choice
>Server:Apache //How can I hide this?
>Keep-Alive:timeout=2, max=200
>Expires:-1
>Date:Sat, 11 May 2013 12:mm:ss GMT
>Content-Type:audio/mpeg
>content-transfer-encoding:binary
>Content-Location:filename.php  //I would also like to obfuscate this
>Content-Length:#######
>Content-Disposition:attachment; filename="suggested-save-name.mp3"
>Content-Description:File Transfer
>Connection:Keep-Alive
>Cache-Control:no-cache
4

1 回答 1

0

Step 1 would be to remove all nonsense headers that are not defined in the HTTP standard.

This will eliminate Content-Description and Content-Transfer-Encoding. Both are useless at best, and might interfere with normal browser operations in the worst case.

Step 2 is to optimize the file delivery. Do not download the MP3 with a HTTP request, access the FILE on the server. Do not use a URL, do use a file path. If the MP3 is right next to your script, this will work:

readfile('./exact-file-name.mp3');

At this point you should usually end up with a working download. If not, try changing the Content-Type to something more generic. audio/mpeg might trigger the audio player in some browser, application/octet-stream should work in most browsers but older Internet Explorer, which do inappropriate content sniffing on certain mime types including this one. application/x-ms-download is supposed to work then.

Make sure the header is sent. PHP does not send HTTP headers if the HTTP body was already startet, and any whitespace including the UTF-8 BOM will trigger body output.

Some comments on your "final" headers in general:

Content-Length: should only have an integer stating the length in bytes, nothing more. Especially no mention of any filename in square brackets.

Content-Transfer-Encoding and Content-Description are still useless.

Content-Location is not needed. If you don't know what it does, omit it. Obfuscation will not work here, the browser needs to know the URL he is accessing. Duplicating this URL in this header does not change anything, obfuscating it will likely break things somewhere.

The two headers you really only need for a download are: Content-Type and (if you want to pre-define a filename for the user) Content-Disposition.

于 2013-05-09T00:11:25.787 回答