Я пытался прочитать аудиофайл из mongoDB, который я сохранил с помощью GridFS. Я мог загрузить файл в систему и воспроизвести из него, но я хотел передавать эти аудио/видео файлы из самой БД и воспроизводить их в браузере. Можно ли как-то это сделать без загрузки файла в систему? Любая помощь была бы хороша.
потоковое аудио / видео файлы из gridFS в браузере
Ответы (2)
Поддержка 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 вы можете это довольно эффективно.
Если другой рецепт не работает, например, с NginX
и 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
только для больших размеров.