3

我是一名实验室讲师,并试图通过将文件保留在 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);
 }

我什至尝试只发送也没有正确传输的纯文本,结果只是乱码。


编辑:

抱歉,我疏忽了我已经尝试过的内容。我确实尝试发送一个简单的文本文件(尝试在记事本中检查 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 语句并相应地增加内容大小来验证这一点,并且该文本没有最终出现在下载的文件中,所以我相对确定换行符不是来自那里。

4

1 回答 1

1

确保 PHP 脚本不包含<?php ?>标签中的空行。一般来说,确保没有其他内容被回显,但文件。

It would be very helpful if you post resulting file contents here, please. Try with a simple one-line text file.

于 2012-09-10T16:41:08.893 回答