从浏览器上的gridFS流式传输音频/视频文件

时间:2013-08-12 11:04:56

标签: php mongodb gridfs

我一直在尝试从使用GridFS存储的mongoDB中读取音频文件。我可以在系统中下载该文件并从中播放,但我想从数据库本身流式传输这些音频/视频文件并在浏览器中播放。无论如何都没有将文件下载到系统吗?任何帮助都会很好。

2 个答案:

答案 0 :(得分:0)

PHP GridFS支持具有MongoGridFSFile::getResource()功能,允许您将流作为资源获取 - 它不会将整个文件加载到内存中。结合fread/echostream_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,您可以非常有效地完成此任务。

答案 1 :(得分:0)

如果other recipe失败,例如NginXphp-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