PHP流开始时不需要的空白字符

时间:2016-01-05 07:10:13

标签: php

我使用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或将其写入流时似乎会发生这种情况。

1 个答案:

答案 0 :(得分:1)

从上面的评论来看,我的猜测是:

  1. 已启用自动output buffering
  2. 某些文件正在发送输出,可能是在开始标记<?之前的空白字符。
  3. 由于输出缓冲,对header()的调用不会失败。要查找输出的发送位置,请在使用以下代码调用header()之前尝试刷新所有活动输出缓冲区

    while (@ob_end_flush())
        ;
    

    如果启用了警告,您应该会看到类似的内容:

    Warning: Cannot modify header information - headers already sent by (output started at path/to/file.php:1)
    

    如果您没有看到任何警告,请检查您的error_reportingerror_logdisplay_errors设置。