通过Zend Framework提供大文件

时间:2009-11-18 10:03:08

标签: php zend-framework

在我们的应用程序中,身份验证是通过一组验证用户等的控制器插件来处理的。

我想仅向经过身份验证的用户提供大型(视频)文件 - 显而易见的方法是通过控制器中的readfile(),但我发现它达到了PHP内存限制 - 可能是来自控制器在某处缓冲。

如何为这一个控制器关闭缓冲?

编辑:感谢关于刷新任何现有输出缓冲的所有有用提示 - 我想我是在寻找在框架内执行此操作的方法吗?

6 个答案:

答案 0 :(得分:4)

有趣的问题......你可以试试:

// ...
public function largeFileAction()
{
    // this clears all active output buffers
    while (ob_get_level()) {
        ob_end_clean();
    }
    readfile('path/to/large/file');
    exit(); // to prevent further request handling
}
//  ...

答案 1 :(得分:2)

好吧,我可能在这里完全错了,但我认为已经读过某个地方必须为ZendLayout和占位符助手启用OB,所以你必须为downloadAction禁用它们(你可能不需要它们无论如何都要提供文件。)

这样的事情会实现你想做的吗?

class DownloadController
{
    public function downloadAction()
    {
        $this->_helper->layout()->disableLayout();
        $this->_helper->viewRenderer->setNoRender(true);
        // authenticate user if not done elsewhere already
        header( /* ... the usual stuff ... */);
        filepassthru(/* some path outside webroot */);
        exit;
    }
}

答案 2 :(得分:2)

正如Tyson所写,您最好的选择(如果您完全控制服务器)是验证用户凭据并将他重定向(302临时重定向)到他可以下载文件的URL。

为防止重复使用此URL,我们使用Lighttpd及其mod_secdownload,它允许您生成在指定时间内有效的哈希值。

nginx有X-Accel-Redirect,Apache有mod_xsendfile

如果您决定实施单独的轻量级Web服务器,还有其他好处(主要是在提供静态文件时降低内存消耗并缩短响应时间)。

如果您决定使用此路由,则必须向服务器添加另一个IP地址,并将Apache仅绑定到一个IP地址,将另一个服务器(轻微的nginx)绑定到另一个服务器,因为它们是Web服务器两者都在端口80上监听。更改其中一个服务器的端口并不是一个好主意,因为很多人无法访问更高端口。

如果添加另一个IP地址不是一个选项,您可以在端口80上安装nginx并将其用作反向代理,以将动态请求传递给Apache,该请求可以侦听另一个端口并提供所有静态文件。

答案 3 :(得分:0)

考虑使用外部脚本输出文件,并使用PHP的passthru函数将其传输到浏览器。

如果在基于Linux的系统上,您可以尝试类似passthru("cat video_file.flv");

的内容

但是,更好的做法是完全避免这种流式传输(来自PHP内部)并向客户端发送301 HTTP重定向到实际静态资源的URL,以便Web服务器可以直接处理它。

答案 4 :(得分:-1)

我认为你不能。据我所知,php在将所有输出发送给请求者之前对其进行缓冲。

您可以使用ini_set()

增加内存限制

答案 5 :(得分:-1)

$handle = fopen('/path/to/file', 'r');
$chunk_size = 8192;

while ($chunk = fread($handle, $chunk_size)) {
    echo $chunk;
    ob_flush();
}

这可能需要一些调整,例如添加正确的标题和必要时以二进制模式阅读,但基本的想法是合理的。我已成功使用此方法发送50多个MB文件,其内存限制为16 MB。