Опитвам се да прочета аудио файл от 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 Range заявки можете да правите това доста ефективно.
Ако другата рецепта е неуспешна, например с 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);
}
FYI:
В този пример:
- Файлът не се осъществява чрез името на файла, а вместо това се осъществява чрез номер, съхранен в метаданните. Съвет: Можете да зададете уникален индекс, за да сте сигурни, че нито едно число не може да се използва два пъти.
- Content-Type също се чете от GridFS, така че не е необходимо да го кодирате твърдо.
- Кеширането на NginX е изключено, за да се активира поточно предаване.
По този начин можете дори да обработвате други неща като видео или html страници. Ако искате да активирате кеширането на NginX, може би извеждайте само X-Accel-Buffering
при по-големи размери.