【问题标题】:header('Content-type: application/octet-stream') cause 0 byte filesheader('Content-type: application/octet-stream') 导致 0 字节文件
【发布时间】:2012-06-25 22:01:06
【问题描述】:

我在 PHP 中使用数据库查询来检索二进制文件。但是当我试图强制下载它时, header('Content-type: application/octet-stream') 行会导致 0 字节文件。如果没有该行,我可以下载包含完整内容的文件。这是一个二进制文件,所以我无法理解为什么该行会导致问题。 代码:

$result = mysql_query("SELECT data FROM stored_file WHERE file_name = '$q'");

while($row = mysql_fetch_array($result))
{
    $file = $row['data'];
}


    header('Content-disposition: attachment; filename='.$q);
    header('Content-type: application/octet-stream');
    header('Content-Length: '.filesize($file));
    header("Pragma: no-cache");
    header("Expires: 0");
    echo $file;

有什么想法吗?谢谢。

【问题讨论】:

  • 注释掉所有标题;启用错误报告并运行您的脚本。发布任何错误消息。
  • 我没有收到任何错误消息。
  • 虽然似乎 filesize($file) 什么也没返回。
  • $file 真的存在吗? PHP 是否抱怨“没有这样的文件”或“权限被拒绝”。注意:$file = $row['data'] 不是 $row['file_name']
  • $文件存在。如果我注释掉标题,它会回显它,“ÖG¤Îů8F'ÖŐ×{ç qfw7´ź$ŘLéŐŚ)ÓťÎ=ÚťZ¸Ş...”出现在浏览器中。如果我把它放在这样的条件下它也可以工作: if($file){ header...} but filesize still not working

标签: php download


【解决方案1】:

filesize() 不会返回有意义的值。

您在$file 中有二进制数据,不是 实际文件名 作为第一个参数的要求。因此你会得到一个错误。 (启用 error_reporting!看不到错误和没有错误是两回事。)

所以你想在那里使用的是strlen($file),而不是filesize()

顺便说一句,application/octet-stream 或其他填充项对强制下载没有用处。 Content-Disposition: 标头对此效果最关键。您仍然可以发送正确的 MIME 类型。

【讨论】:

  • 非常感谢!使用 Content-Length 标头是否至关重要?关于错误报告。我在 php.ini 甚至在代码中启用了它: ini_set('display_errors',1);错误报告(E_ALL);所以我不明白为什么我没有收到错误消息。
  • 作为最后的手段,在脚本顶部尝试set_error_handler("var_dump");。 Content-Length: 标头被广泛认为是次要的,通常没有它也可以工作。仅当您还像网络服务器一样实现 Range: headers 等时,才需要有效负载元数据。
【解决方案2】:

通过查看查询,我猜$row['data'] 是存储的二进制数据。要设置正确的 Content-Length 标头,您应该使用 mb_strlen($row['data']);。如果您的机器上没有激活多字节支持(mb_ 函数),请使用 strlen()。但请注意,这可能会导致错误的结果,因为二进制数据实际上可能包含 EOF 字节序列并返回太短的长度。使用 mb_strlen 函数,您就处于保存状态。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-11
    • 2013-12-28
    • 2011-04-22
    • 2012-05-07
    • 2011-01-26
    • 1970-01-01
    相关资源
    最近更新 更多