我作为一名实验室讲师,试图通过将文件保留在 webroot 之上并强制他们登录(通过大学的 LDAP 进行身份验证)来确保我的学生无法过早下载他们的入门文件,验证它是否已经过版本然后 time 使用 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);
}
我什至尝试只发送纯文本,但也无法正确传输,最后只是乱码。
Edit:
抱歉,我疏忽了指定我已经尝试过的内容。我确实尝试发送一个简单的文本文件(尝试在记事本中检查 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
Update:
在其中一台服务器上禁用 gzip 压缩,文件仍然损坏。删除了ob_clean(); flush()
并且文本文件开始清晰地通过(无法相信您在互联网上阅读的所有内容:/)。
Zip 文件仍然损坏,但我的 PDF 现在可以读取了。做了更多查看,似乎在文件的开头添加了一个额外的换行符。回顾一下文本文件,它的前面确实有一个额外的换行符,并且缺少最后一个字符。正如预期添加+1
到 Content-Length 标头让最后一个字符通过,仍然寻找前置换行符的来源。另外,如果我注释掉readfile
我得到一个仅包含 CRLF 的文件(0d0a
) in it.
框架通常使用视图和布局“包装”来自控制器的内容,但两者都设置为空白文件,并且头控制器检查它们是否为空白,然后跳过该行以回显生成的 HTML。即便如此exit(0)
应确保在传输后仅调用析构函数。我通过在布局和视图中放置 echo 语句并相应地增加内容大小来验证这一点,并且文本不会最终出现在下载的文件中,因此我相对确定换行符不是来自那里。