【问题标题】:How do I fix this PHP download script, which is corrupting files?如何修复这个损坏文件的 PHP 下载脚本?
【发布时间】:2011-06-13 09:37:07
【问题描述】:

我有一个强制下载脚本,它可以在 PDF 和纯文本中产生良好的效果,并且可以使用 ZIP 存档(它们在 Windows 中工作,而不是在 Linux 中工作)。但是,应用程序文件和图像都失败了。这些构成了我必须处理的绝大多数文件。正如我在这里看到的类似主题所建议的那样,压缩所有下载不是一种选择。

失败的文件下载到完整大小,并以正确的名称写入磁盘。尝试打开它们会导致错误消息,该消息因类型而异。在 hexdump 中比较下载的文件和它们的原始文件,我可以看到脚本在每个下载文件的开头插入以下字符:

ef bb bf

然后,下载的文件会复制原始文件,直到它停止在指定大小处 - 因此原始文件的最后 6 个字符总是丢失。

不幸的是,我对二进制文件是如何构成的、这些字符可能意味着什么以及脚本如何/为什么插入它们一无所知。

这是原样的脚本:

$file = '94.ppt';
$path = $_SERVER['DOCUMENT_ROOT']."/relative/path/";
$full_path = $path.$file;
if ($fd = fopen ($full_path, "r")) {
    $fsize = filesize($full_path);
    $path_parts = pathinfo($full_path);
    $ext = strtolower($path_parts["extension"]);
    switch ($ext) {
        case "pdf":
            header("Content-type: application/pdf");
            header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
        break;
        case "txt":
            header("Content-type: text/plain");
            header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
        break;
        case "jpg":
            header("Content-type: image/jpeg");
            header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
        break;
        case "ppt":
            header("Content-Type: application/vnd.ms-powerpoint");
            header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
        break;
        default;
            header("Content-type: application/octet-stream");
            header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
    }
    header("Content-Transfer-Encoding: binary");
    header("Content-length: $fsize");
    header("Cache-control: private");
    while(!feof($fd)) {
        $buffer = fread($fd, 2048);
        echo $buffer;
    }
}
fclose ($fd);
exit;

开发系统是 Apache 2.2.14 (Ubuntu) 上的 PHP 5.3.2-1。生产主机是 Apache 2.0.63(某种 Linux)上的 PHP 5.2.9。

【问题讨论】:

  • 不确定这是您帖子中的错字还是实际代码“默认”;应该是:不是;

标签: php download


【解决方案1】:

您的 PHP 脚本文件似乎以 UTF-8 with BOM 编码,位于文件开头的 <?php 分隔符之前。这些字节在您的实际输出之前发送,因此会损坏您的数据。

您只需将其删除并将您的编辑器配置为不使用 UTF-8 的 BOM。

【讨论】:

  • 谢谢大家,脚本现在可以完美运行了。原因是 Notepad++ 中的编码设置。我自己要花很长时间才能找到它。
  • @hnmcc:这是一个常见问题,尤其是因为 UTF-8 不需要 BOM,因为只有一个字节顺序 - 好吧,除了自动编码检测。
  • 我有一个注入了某种损坏的图像文件,也许它是 bom。但是,我从未编辑过该文件。没有注入内容的文件是通过网络应用程序上传并通过 FTP 下载的,之前或之后没有奇怪的代码。但是,当通过隐藏文件在网络上的网络应用程序下载时,会出现导致文件损坏的奇怪代码。文件正在被 fread 读取,一次 1024 字节的循环,在每个循环中发送到缓冲区。不知何故,那里发生了损坏,但前提是我编辑了包含循环的 php 文件。
【解决方案2】:

EF BB BF 是标准的 UTF-8 byte order mark。有些人有reported,当您包含在脚本中的某些 PHP 文件是 UTF-8 编码时,就会发生这种情况;某些版本的 PHP 通过发送 UTF-8 字节顺序标记对此做出反应。上面的链接建议在脚本开头调用 ob_start() 并在开始推出文件内容之前调用 ob_end_clean() - 这样字节顺序标记就会被捕获在输出缓冲区中。

此外,您可以简单地使用 fpassthru 将文件通过管道传输到输出,而不是循环读取和写入。

【讨论】:

  • 感谢您:目前我面临着获得一些东西——任何东西——有效的压力。但我确实计划在夏天晚些时候再次查看该项目。
【解决方案3】:

EF BB BF 是 UTF-8 编码 Byte Order Mark (BOM)。我怀疑有一些配置选项可以关闭 BOM。

编辑:文件编辑器应允许您在以相关字符编码(例如 UTF-8)保存文件时关闭 BOM。

【讨论】:

  • 如果它得到输出,我不会感到惊讶,因为脚本(或它包含的某些脚本)被保存为 UTF-8,并且编辑器预先添加了一个 BOM,该 BOM 现在正在传递到输出。配置设置无法解决此问题
  • 编辑器中的配置设置将 :-) 此外,OP 提到图像失败,因此它不能是 BOM 前缀源文件。
  • 触摸。 :) 我在考虑 PHP 设置,而不是编辑器设置。
  • 我的回答也不清楚,所以感谢您的评论:-)
  • 谢谢大家,脚本现在可以完美运行了。原因是 Notepad++ 中的编码设置。我自己要花很长时间才能找到它。
猜你喜欢
  • 2016-03-01
  • 1970-01-01
  • 2011-09-10
  • 2015-07-16
  • 1970-01-01
  • 2018-10-14
  • 2014-06-05
  • 2012-05-16
相关资源
最近更新 更多