PHP:下载的二进制文件在最后获得一个额外的字节(0x0a)
Posted
技术标签:
【中文标题】PHP:下载的二进制文件在最后获得一个额外的字节(0x0a)【英文标题】:PHP: Downloaded binary file gets an additional byte (0x0a) at the end 【发布时间】:2011-12-05 10:46:42 【问题描述】:php 版本 5.2.17
我有以下用于下载二进制文件的 PHP 脚本:
<?php
$download_dir = '.';
$download_file = $_GET['get'];
$path = $download_dir.'/'.$download_file;
if(file_exists($path))
$size = filesize($path);
header('Content-Type: application/x-download');
header('Content-Disposition: attachment; filename='.$download_file);
header('Content-Length: '.$size);
header('Content-Transfer-Encoding: binary');
readfile($path);
else
echo "<font face=$textfont size=3>";
echo "<center><br><br>The file [<b>$download_file</b>] is not available for download.<br>";
?>
用于调用此脚本的 URL:
http://myserver/cur/downloads/test.php?get=FooBar_Setup.exe
下载正常,但下载的文件附加了一个额外的字节 (0x0a)。 响应的标头还显示了比请求文件的大小大一个字节的 Content-Length:
HTTP/1.1 200 OK
Date: Mon, 05 Dec 2011 10:29:32 GMT
Server: Apache/2.2
Content-Disposition: attachment; filename=FooBar_Setup.exe
Content-Length: 1417689
Content-Transfer-Encoding: binary
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/x-download
服务器上文件的大小为 1417688 字节。
我已验证 filesize($path)
返回正确的文件大小。似乎 PHP 用 filesize($path)+1
更改了 Content-Length 标头。
我在两个不同的文件中看到了这种行为。
如何防止 PHP 将 0x0a 附加到下载的二进制文件?
【问题讨论】:
您应该清理该文件名。人们可以使用该脚本下载他们想要的任何文件(包括脚本本身)。 尝试删除 ?> 或在 readfile() 函数后添加退出语句。 @SebastianPaaskeTørholm 非常大 +1。如此之大,以至于我觉得仅单击 +1 不足以说明这一点的重要性。 是的,当然应该对文件名进行清理。我只是想让这篇文章的脚本简短。不知道结束标记后的内容进入响应。 【参考方案1】:您很可能在结束 ?>
之后有一个额外的空白行,它与数据一起回显。关闭 ?>
在 PHP 文件末尾始终是可选的。将其排除在外是防止此类问题的好习惯。
Content-Length 更改的原因是因为 HTTP 服务器(或 PHP?)忽略它并添加一个新的以匹配实际数据响应,然后再将其发送到浏览器,所以我认为你可以离开那出来。 (如果您确实设法使用错误的 Content-Length 发送数据,我发现浏览器会表现得非常很奇怪。)
【讨论】:
【参考方案2】:您的 PHP 脚本在结束 ?>
标记之后有一个换行符。这就是杂散换行符的来源。
避免此问题的最佳方法(顺便说一下,在 SO 上很多出现)是不使用结束 ?>
。 PHP 不需要它,它有助于避免这个问题。
【讨论】:
【参考方案3】:尝试在读取文件后添加退出:
//ob_clean();
//flush();
readfile($path);
exit;
或者,如果当前文件中只有 1 块 php 代码,您可以删除 ?>:
<?php
$download_dir = '.';
$download_file = $_GET['get'];
$path = $download_dir.'/'.$download_file;
if(file_exists($path))
$size = filesize($path);
header('Content-Type: application/x-download');
header('Content-Disposition: attachment; filename='.$download_file);
header('Content-Length: '.$size);
header('Content-Transfer-Encoding: binary');
readfile($path);
exit;
else
echo "<font face=$textfont size=3>";
echo "<center><br><br>The file [<b>$download_file</b>] is not available for download.<br>";
【讨论】:
【参考方案4】:压缩也会导致额外的字节出现在下载的文件中。在脚本的顶部,添加:
ini_set("zlib.output_compression", "off");
为该 PHP 脚本禁用它。或者,或者另外,您可能想要验证您的 Web 服务器是否也没有压缩该脚本的输出。
【讨论】:
以上是关于PHP:下载的二进制文件在最后获得一个额外的字节(0x0a)的主要内容,如果未能解决你的问题,请参考以下文章