Php 通过Zend框架提供大文件

Php 通过Zend框架提供大文件,php,zend-framework,Php,Zend Framework,在我们的应用程序中,身份验证是通过一组验证用户的控制器插件来处理的 我只想为经过身份验证的用户提供一个大的(视频)文件——显而易见的方法是通过控制器中的readfile()实现这一点,但我发现它达到了PHP内存限制——可能控制器的输出被缓冲在某个地方 如何仅为这一个控制器关闭缓冲 编辑:感谢您提供有关刷新任何现有输出缓冲区的所有有用提示-我想我是专门在框架内寻找这样做的方法?我认为您实际上不能。据我所知,php在将输出发送给请求者之前会缓冲所有输出 考虑到使用外部脚本输出文件,可以使用增加内存限

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

我只想为经过身份验证的用户提供一个大的(视频)文件——显而易见的方法是通过控制器中的readfile()实现这一点,但我发现它达到了PHP内存限制——可能控制器的输出被缓冲在某个地方

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


编辑:感谢您提供有关刷新任何现有输出缓冲区的所有有用提示-我想我是专门在框架内寻找这样做的方法?

我认为您实际上不能。据我所知,php在将输出发送给请求者之前会缓冲所有输出


考虑到使用外部脚本输出文件,可以使用

增加内存限制,并使用PHP的passthru函数将其流式传输到浏览器

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


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

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

// ...
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
}
//  ...

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

好的,我可能在这里完全错了,但我认为必须启用OB才能让ZendLayout和占位符帮助程序工作,所以您必须禁用它们才能进行下载操作(无论如何,你可能不需要他们来提供文件)

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

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;
    }
}

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

为了防止重用此URL,我们使用Lighttpd和its,它允许您生成在指定时间内有效的哈希

nginx有,Apache有

如果您决定实现一个单独的轻量级web服务器,那么还有其他好处(主要是在提供静态文件的同时降低内存消耗和更快的响应时间)

如果您决定走这条路线,您要么必须向服务器添加另一个IP地址,并仅将Apache绑定到一个IP地址,另一个服务器(轻量级的nginx)因为它们都是web服务器,所以都监听端口80。更改其中一个服务器的端口不是一个好主意,因为很多人无法访问更高的端口


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

不正确,PHP具有控制输出缓冲区的功能。正确,您不能完全关闭它,但您肯定可以事件它达到内存限制。谢谢,这是专门在Zend Framework环境中进行的吗?抱歉,这不是Zend特定的,这只是我知道的防止大文件填满内存限制的唯一方法(当然,除了使用不占用PHP进程的方法之外)我认为这不是特定于Zend的,只要框架不试图控制输出缓冲区。我已经设法在32MB的环境中以这种方式输出700MB的文件(这是由于执行时间的限制)。这意味着未经身份验证的人员可以公开访问资源,只要他们知道URL,在Zend_控制器操作中使用
passthru
,仍然会遇到此原始问题中描述的相同问题-控制器(特别是响应对象)将在输出结果之前缓存结果。
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;
    }
}