我正在使用 PHP从我的网站重定向下载,基本上是读取远程流并从我的站点回显它(这是我在需要下载绕过防火墙时快速开发的实用程序).
最后我查了一下,这个工作得很好.我想昨天添加一个功能,发现返回的流现在前面有4个空白字符.我无法理解那些来自哪里.无论发生什么,下载的文件总是以(4个空格,在记事本中确保“查看不可见字符”模式)开始,否则不会改变.
[编辑]回答评论:这些空格不是原始文件的一部分.为了测试这种行为,我下载了原始文件(用于简单测试的JPG),然后通过代理下载它并将两者分开. 4字节差异,可以通过删除代理文件的前四个字符来解决.当然,在我解决差异之前,代理文件是不可用的.
[Edit2]这些字符似乎也不是BOM.请记住,其中有4个. Wikipedia tells us UTF-8 BOM的长度为3个字节:
The UTF-8 representation of the BOM is the byte sequence
0xEF,0xBB,0xBF
. A text editor or web browser misinterpreting the text as ISO-8859-1 or CP1252 will display the characters
for this.
现在我想不出我在代码中做出的任何可以解释这种新行为的变化.也许是PHP的更新?我在这台服务器上还没有phpinfo(今晚会有一个),但这是在最新的Ubuntu 14.04上运行的.
我想我必须修补代码来解决它.只有我不知道怎么做.也许有人会有领先的尝试?
以下是代码:
function download($url, $filename, $mimetype) {
/* prepare filename */
// [prepare $filename]
// mess with the headers to bypass the proxy
header('Content-Type: ' . $mimetype['mime']);
header("Content-Disposition: attachment; filename=$filename");
// and now the file content
IOUtils::readfile($url);
}
在IOUtils中:
<?php
/**
* Static utilities for IO.
*
* @author Cyrille Chopelet
*/
class IOUtils {
/**
* Copies the content of the file as a stream into the response stream.
* <p>
* This could seem to be a useless override for the PHP readfile function,
* but this is bufferized so that available memory is not overflowed
* when reading a large file.
*
* @param string $path the URI to the file
*/
public static function readfile($path) {
$handle = fopen($path, 'rb');
while (!feof($handle)) {
echo fread($handle, 8192);
ob_flush();
}
fclose($handle);
}
}
?>
在调用下载功能之前没有输出.这显然会失败,因为一旦输出开始就无法调用头.这意味着在读取$handle或将其写入流时似乎会发生这种情况.
最佳答案 从上面的评论来看,我的猜测是:
>启用自动output buffering.
>某些文件正在发送输出,可能是在开始标记<?之前的空白字符.
由于输出缓冲,对header()的调用不会失败.要查找输出的发送位置,请在使用以下代码调用header()之前尝试刷新所有活动的输出缓冲区
while (@ob_end_flush())
;
如果启用了警告,您应该看到与此类似的内容:
Warning: Cannot modify header information - headers already sent by (output started at path/to/file.php:1)
如果您没有看到任何警告,请检查您的error_reporting,error_log和display_errors设置.