文件下载已损坏


File download is corrupt

我是一名实验室讲师,试图确保我的学生不能提前下载他们的入门文件,方法是将文件保存在webroot之上,并强迫他们登录(通过大学的LDAP进行身份验证),验证是否已过发布时间,然后使用readfile向他们发送文件。不幸的是,我发送的任何文件都被破坏了。

我的代码是:

if (file_exists($path)) {
     //header('Content-Description: File Transfer');
     header('Content-Type: application/octet-stream');
     header('Content-Disposition: attachment; filename='.basename($path));
     //header('Content-Transfer-Encoding: binary');
     header('Expires:' . date('r', 0));
     header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
     //header('Pragma: public');
     header('Content-Length: ' . filesize($path));
     //ob_clean();
     //flush();
     readfile($path);
     exit(0);
 }

我甚至试着只发送纯文本,但也没有正确传输,结果只是胡言乱语。


编辑:

对不起,我没有详细说明我已经尝试过的内容。我确实尝试过发送一个简单的文本文件(试图在记事本中查看pdf文件以查找PHP警告有点麻烦)。

我发送了一个只包含This is plain text内容的文件,结果完全是胡言乱语。大多数是不可打印的字符。1f 8b 08 00 00 00 00 00 00 03 0b c9 c8 2c 56 00 a2 82 9c 00


更新:

在其中一台服务器上禁用了gzip,文件仍然损坏。删除了ob_clean(); flush(),文本文件开始干净地通过(简直不敢相信你在互联网上读到的任何东西:/)。

Zip文件仍然损坏,但我的PDF现在可读了。再看一看,似乎在文件的开头添加了一个额外的换行符。回过头来看文本文件,它的前面确实有一个额外的换行符,最后一个字符也不见了。正如预期的那样,将+1添加到Content-Length标头可以让最后一个字符通过,仍然可以查找前缀换行符的来源。此外,如果我注释掉readfile,我会得到一个只有CRLF(0d0a)的文件

框架通常用视图和布局"包装"控制器中的内容,但两者都设置为空白文件,主控制器检查它们是否为空,然后跳过行以回显生成的HTML。即便如此,exit(0)也应该确保在传输之后只调用析构函数。我通过在布局和视图中放置echo语句并相应地增加内容大小来验证这一点,并且文本不会出现在下载的文件中,所以我相对确信换行符不是来自那里。

确保PHP脚本不包含<?php ?>标记中的空行。一般情况下,请确保除了文件之外,没有其他内容得到响应。

如果您在这里发布生成的文件内容,将非常有帮助。尝试使用一个简单的单行文本文件。