PHP流开头的不需要的空白字符

我正在使用 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设置.

点赞