在我们的应用程序中,身份验证是通过一组验证用户等的控制器插件来处理的。
我想仅向经过身份验证的用户提供大型(视频)文件 - 显而易见的方法是通过控制器中的readfile(),但我发现它达到了PHP内存限制 - 可能是来自控制器在某处缓冲。
如何为这一个控制器关闭缓冲?
编辑:感谢关于刷新任何现有输出缓冲的所有有用提示 - 我想我是在寻找在框架内执行此操作的方法吗?
答案 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。