1

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.

4

2 回答 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

如果另一个配方失败,例如使用NginXand 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 回答