最佳做法及;使用PHP为.mp3或.pdf文件下载提供HTML标题的语法(步骤1:删除BOM)

最佳做法及;使用PHP为.mp3或.pdf文件下载提供HTML标题的语法(步骤1:删除BOM),php,syntax,header,notepad,byte-order-mark,Php,Syntax,Header,Notepad,Byte Order Mark,我正在提供一个.mp3文件(作为下载对话框,最终用户可以在其中重命名和保存文件)。在论坛上,甚至在php手册的评论中,都有很多相互冲突的建议 我希望解决我的问题,并在这里创建一个关于如何最好地实现这一目标的参考:即,一个清晰的“最佳实践总结”,可以通过最有效的方式开始交付可下载文件的php程序员来使用 如果您能检查一下这里的代码并提出修改建议,我将不胜感激。这是一个帮助艺术家自我发布音乐、书籍等的网站的一部分 为了进行测试,我将其作为index.php上传到我的服务器;也许这也是问题的一部分 此

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

我希望解决我的问题,并在这里创建一个关于如何最好地实现这一目标的参考:即,一个清晰的“最佳实践总结”,可以通过最有效的方式开始交付可下载文件的php程序员来使用

如果您能检查一下这里的代码并提出修改建议,我将不胜感激。这是一个帮助艺术家自我发布音乐、书籍等的网站的一部分

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

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

我曾多次认为我的问题在于重要的“内容长度”标题的语法,或者标题的顺序,所以我尝试了所有这些的几个版本,但都没有中断下载

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

我希望这是脚本语法中的一个简单错误(或多个错误),或者是我创建和保存.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;

第一步是删除HTTP标准中未定义的所有无意义头

这将消除
内容描述
内容传输编码
。两者充其量都是无用的,在最坏的情况下可能会干扰正常的浏览器操作

第2步是优化文件传递。请勿使用HTTP请求下载MP3,请访问服务器上的文件。不要使用URL,请使用文件路径。如果MP3就在您的脚本旁边,这将起作用:

readfile('./exact-file-name.mp3');
在这一点上,你通常应该得到一个有效的下载。如果没有,请尝试将
内容类型更改为更通用的类型
audio/mpeg
可能会触发某些浏览器中的音频播放器,
application/octet stream
应该可以在大多数浏览器中工作,但较旧的Internet Explorer会对某些mime类型(包括此类型)进行不适当的内容嗅探<代码>应用程序/x-ms-download
应该可以正常工作

确保发送了标题。如果HTTP主体已经是startet,PHP不会发送HTTP头,任何空格(包括UTF-8 BOM)都将触发主体输出

关于“最终”标题的一般评论:

内容长度:
应该只有一个整数,以字节表示长度,仅此而已。尤其是方括号中没有提到任何文件名

内容传输编码
内容描述
仍然没有用

不需要内容位置
。如果你不知道它是做什么的,就省略它。模糊处理在这里不起作用,浏览器需要知道他正在访问的URL。在这个标题中复制这个URL不会改变任何东西,混淆它可能会破坏某些东西


下载时真正需要的两个标题是:
内容类型
和(如果要为用户预定义文件名)
内容配置

Danke Sven。到目前为止,这还不起作用。根据你的建议,我进一步缩减了我的测试脚本(我在上面添加了“参考3”),但我遇到了同样的问题。我也希望有一些附带的评论:为什么即使在我测试了不同的内容长度(甚至输入了不正确的值)之后,我仍然会得到相同的错误?另外,为什么文件路径前需要“.”。我以为period在php中只用作连接运算符?有人知道为什么这可能不起作用吗?我是否必须使用$variable uuu来使用php打开文件?再次提前感谢“不起作用”对你意味着什么?能否将Liveheaders插件安装到Firefox中,启动它并在单击下载后获取从服务器发送的标题。我觉得你的本地环境有点不对劲。顺便说一句:
内容长度:\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\[“song.mp3”]
当然错了,我想你刚才用一个整数替换了它,表示mp3文件中的字节数。让Web服务器为您创建此标题,即不要自己添加此标题。我所说的“不起作用”只是指它会出现与我在文章中提到的相同的问题(将文件作为文本转储到浏览器中)。我每次都会在几个不同的地方环境中进行测试;所以我猜问题一直都在代码或我的服务器/主机问题上,至少手头有问题(二进制文件作为文本转储到浏览器中),只是由win Notepad添加的BOM表。我以前在许多其他帖子上读过关于BOM的文章;我没有意识到它实际上是什么以及如何删除它。正如@martin geisler所指出的,我刚刚从中了解到,对于简单的使用(例如,如果在这里抛出下载是唯一需要的任务),您可以在记事本中保存为ANSI,并避免在windows中键入编辑器时弹出BOM.windows记事本(不是真正的编辑器);-}
<?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;
>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
readfile('./exact-file-name.mp3');