PHP Version 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到下载的二进制文件?
您很可能在关闭?>
之后有一个额外的空行,该空行正在与数据回显。结束的?>
在PHP文件的末尾总是可选的。省略它是防止这类问题的好方法。
Content-Length变化的原因是因为HTTP服务器(或PHP?)忽略了它,并在将其发送到浏览器之前添加了一个新的以匹配实际的数据响应,所以我认为您可以忽略它。(如果你设法发送数据与错误的Content-Length,我发现浏览器可以行为非常奇怪)
PHP脚本中在结束的?>
标记之后有一个换行符。这就是多余的换行符的来源。
?>
。PHP不需要它,它有助于避免这个问题。
尝试在readfile后添加exit:
//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>";
}
压缩还可能导致下载文件中出现额外的字节。在脚本的顶部,添加:
ini_set("zlib.output_compression", "off");
为该PHP脚本禁用它。或者,您可能想要验证您的web服务器也没有为该脚本压缩您的输出。