为什么这个PHP发送文件会破坏数据?

时间:2013-02-27 17:14:00

标签: php zend-framework

我有一个简单地在服务器上存储文件的项目。当有人想下载文件时,我必须通过中间控制器(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尝试过它。这两个都给了我相同的结果。

提前感谢您的帮助!

瑞克

2 个答案:

答案 0 :(得分:2)

可能导致许多框架上的文件下载问题的一件事是丢失\ n,这些通常发生在?>之后。 PHP,并最终发送意外\ n与您的数据。这些\ n在发送HTML时完全无害,但会破坏任何其他文件。

PHP脚本不要求您关闭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,它更加内存友好,并将为您处理缓存标题。