我是一名实验室教师,并且正在努力确保我的学生不能通过将文件保留在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
更新
禁用其中一台服务器上的gzipping,文件仍然损坏。删除了ob_clean(); flush()
并且文本文件开始干净利落(不能相信你在互联网上阅读的内容:/)。
Zip文件仍然损坏,但我的PDF现在可读。还有一些看起来似乎在文件的最开头添加了一个额外的换行符。回顾文本文件,它在前面有一个额外的换行符,并且缺少最后一个字符。正如预期的那样,将+1
添加到Content-Length标头可以让最后一个角色通过,仍然可以查找前置换行符的来源。另外,如果我注释掉readfile
,我会收到一个只包含CRLF(0d0a
)的文件。
框架通常使用视图然后布局来“封装”来自控制器的内容,但两者都设置为空白文件,并且头控制器检查它们是否为空,然后跳过该行以回显生成的HTML。即使这样,exit(0)
也应该确保在传输之后只调用析构函数。我通过在布局和视图中放置echo语句并相应地增加内容大小来验证这一点,并且文本不会在下载的文件中结束,所以我相对确定换行不是来自那里。
答案 0 :(得分:1)
确保PHP脚本不包含<?php ?>
个标记中的空行。通常,确保没有回显其他内容,但文件。
如果您在此处发布结果文件内容,那将非常有用。尝试使用简单的单行文本文件。