0

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

在此先感谢您的帮助!

瑞克

4

2 回答 2

2

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

PHP 脚本不要求您关闭 PHP 标记,最好不要关闭它。例外情况是当您使用 PHP 模板(在视图中)时,您显然必须关闭它们。

  • 删除您正在访问的控制器(包括控制器)使用的所有模型和组件的?>标签
  • 确保在同一文件中的 <?php 标记之前没有输入
  • 确保您禁用了此操作的布局和视图渲染(似乎已正确完成)
于 2013-02-27T17:28:04.247 回答
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,它对内存更友好,并且会为您处理缓存标头。

于 2013-02-27T17:28:25.503 回答