我有一个简单地在服务器上存储文件的项目。当有人想下载文件时,我必须通过中间控制器(Zend框架)传递请求,以便为文件提供一些保护。
当有人请求文件时,文件会被下载到客户端浏览器,但是在我的所有测试中,文件总是会被损坏(尽管它的字节大小合适)。有人能告诉我这里我做错了吗?
public function downloadAction() {
$this->_helper->layout->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$files = new Application_Model_DbTable_Files();
$file = $files->getFileForDownload($this->_getParam('id'), Zend_Auth::getInstance()->getIdentity()->id);
$config = Zend_Registry::get('config');
$this->_helper->layout->disableLayout();
$this->_helper->viewRenderer->setNoRender();
if (file_exists($config['mindful']['path'] . $file)) {
$this->getResponse()->setHeader('Content-type', 'application/octet-stream');
$this->getResponse()->setHeader('Content-Disposition', 'inline; filename=' . basename($file), false);
$this->getResponse()->setBody(readfile($config['mindful']['path'] . $file));
}
}
正如您所看到的,我已经使用Zend方法以及标准PHP尝试过它。这两个都给了我相同的结果。
提前感谢您的帮助!
瑞克
答案 0 :(得分:2)
可能导致许多框架上的文件下载问题的一件事是丢失\ n,这些通常发生在?>之后。 PHP,并最终发送意外\ n与您的数据。这些\ n在发送HTML时完全无害,但会破坏任何其他文件。
PHP脚本不要求您关闭PHP标记,并且最好不要关闭它。例外情况是您使用PHP模板(在视图中),您显然必须关闭它们。
答案 1 :(得分:1)
readfile
不会返回文件内容,而是立即输出。返回值是字节数,因此当前将其附加到您的响应正文。这可能是造成腐败的原因。
您可以先通过发送标头继续使用readfile
,然后直接调用它:
$this->getResponse()->setHeader('Content-type', 'application/octet-stream');
$this->getResponse()->setHeader('Content-Disposition', 'inline; filename=' . basename($file), false);
$this->getResponse()->sendHeaders();
readfile($config['mindful']['path'] . $file);
或者如果文件非常小,您可以坚持使用当前的方法并改为使用file_get_contents
:
$this->getResponse()->setBody(file_get_contents($config['mindful']['path'] . $file));
请注意,这些方法都不提供任何缓存(例如,如果自标题以后进行修改,则处理)。
您还可以考虑使用X-Sendfile,它更加内存友好,并将为您处理缓存标题。