我使用PHP从我的网站重定向下载,基本上是读取远程流并从我的站点回显它(这是我在需要下载绕过防火墙时快速开发的实用程序)。
最后我查了一下,这个工作得很好。我想昨天添加一个功能,发现返回的流现在前面有4个空白字符。我无法理解那些来自哪里。无论发生什么情况,下载的文件始终以开头(4个空格,确保用'查看不可见字符'模式在Notepad ++中),否则不会改变。
[编辑]回答评论:这些空格不是原始文件的一部分。为了测试这种行为,我下载了原始文件(用于简单测试的JPG),然后通过代理下载它并将两者分开。 4字节差异,可以通过删除代理文件的前四个字符来解决。当然,在我解决差异之前,代理文件是不可用的。
[Edit2]这些字符似乎也不是BOM。请记住,其中有4个。 Wikipedia tells us UTF-8 BOM的长度为3个字节:
BOM的UTF-8表示是字节序列
0xEF,0xBB,0xBF
。将文本误解为ISO-8859-1或CP1252的文本编辑器或Web浏览器将为此显示字符
。
现在我无法想到我在代码中做出的任何可以解释这种新行为的变化。也许是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);
}
}
?>
在调用download
函数之前没有输出。这显然会失败,因为一旦输出开始就无法调用header
。这意味着在阅读$handle
或将其写入流时似乎会发生这种情况。
答案 0 :(得分:1)
从上面的评论来看,我的猜测是:
<?
之前的空白字符。由于输出缓冲,对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
设置。