I have been trying to read an audio file from mongoDB which i have stored using GridFS. I could download the file in the system and play from it but I wanted to stream those audio/video files from the DB itself and play it in the browser. Is there anyway to do that without downloading the file to the system? Any help would be good.
问问题
2235 次
2 回答
0
PHP GridFS 支持有一个MongoGridFSFile::getResource()函数,允许您将流作为资源获取- 它不会将整个文件加载到内存中。fread/echo
与或stream_copy_to_stream结合使用,您可以防止将整个文件加载到内存中。使用 stream_copy_to_stream,您可以简单地将 GridFSFile 流的资源复制到 STDOUT 流:
<?php
$m = new MongoClient;
$images = $m->my_db->getGridFS('images');
$image = $images->findOne('mongo.png');
header('Content-type: image/png;');
$stream = $image->getResource();
stream_copy_to_stream( $stream, STDOUT );
?>
或者,您可以fseek()
在返回的$stream
资源上使用仅将部分流发送回客户端。结合HTTP Range requests,您可以非常有效地做到这一点。
于 2013-08-12T11:16:27.940 回答
0
如果另一个配方失败,例如使用NginX
and php-fpm
,因为STDOUT
在 中不可用fpm
,您可以使用
fpassthru($stream);
代替
stream_copy_to_stream( $stream, STDOUT );
所以一个完整的解决方案看起来像:
function img($nr)
{
$mongo = new MongoClient();
$img = $mongo->ai->getGridFS('img')->findOne(array('metadata.nr'=>$nr));
if (!$img)
err("not found");
header('X-Accel-Buffering: no');
header("Content-type: ".$img->file["contentType"]);
header("Content-length: ".$img->getSize());
fpassthru($img->getResource());
exit(0);
}
供参考:
在这个例子中:
- 文件不通过文件名访问,而是通过存储在元数据中的数字访问。提示:您可以设置唯一索引以确保没有数字可以重复使用。
- Content-Type 也是从 GridFS 读取的,因此您不需要对其进行硬编码。
- NginX 缓存已关闭以启用流式传输。
通过这种方式,您甚至可以处理其他内容,例如视频或 html 页面。如果你想启用 NginX 缓存,也许只能输出X-Accel-Buffering
更大的尺寸。
于 2017-03-06T18:49:17.167 回答