Я пытался прочитать аудиофайл из mongoDB, который я сохранил с помощью GridFS. Я могу загрузить файл в систему и играть с ним, но я хотел бы передать эти аудио / видео файлы из самой базы данных и воспроизвести их в браузере. Есть ли способ сделать это, не загружая файл в систему? Любая помощь будет хорошей.
Поддержка 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:
В этом примере:
Таким образом, вы можете обрабатывать другие вещи, такие как видео или html-страницы. Если вы хотите включить кеширование NginX, возможно, только выход X-Accel-Buffering
для больших размеров.