передача аудио из mongodb в тег audio

#javascript #node.js #mongodb #html5-audio #gridfs

#javascript #node.js #mongodb #html5-аудио #gridfs

Вопрос:

Для моего проекта я пытаюсь создать аудиоплеер. Аспект хранения файлов в базе данных для меня новый, поскольку раньше я сохранял только строки.

До сих пор то, что я смог сделать, это:

  1. Сохраните аудиофайл в базе данных.(Я ссылаюсь здесь на файл для простоты, но в будущем он будет загружен)

  2. Извлеките аудиофайл как объект.

  3. Сохраните аудиофайл в общедоступной папке для использования.

Код на стороне сервера(код маршрута отделен от кода сервера)

 let fs = require('fs');
var bodyParser = require('body-parser')
var urlencodedParser = bodyParser.urlencoded({
  extended: false
})

const MongoClient = require('mongodb').MongoClient;
const Binary = require('mongodb').Binary;
const ObjectId = require('mongodb').ObjectId;

module.exports = function(app) {

    app.get('/music', function(req, res) {

      //STEP ONE

      var data = fs.readFileSync(__dirname   '/../public/recordings/Piso 21 - Puntos Suspensivos.mp3');
      var insert_data = {};
      insert_data.name = 'Piso 21 - Puntos Suspensivos.mp3';
      insert_data.file_data = Binary(data);

      MongoClient.connect("mongodb://localhost/songs", {
        useNewUrlParser: true
      }, function(err, db) {
        if (err) throw err;
        var dbo = db.db("songs");
        dbo.collection("song").insertOne(insert_data, function(err, res) {
          if (err) throw err;
          console.log("1 document inserted");
          db.close();
        });
      });

      //STEP TWO

      MongoClient.connect("mongodb://localhost/songs", {
        useNewUrlParser: true
      }, function(err, db) {
        if (err) throw err;
        var dbo = db.db("songs");
        dbo.collection("song").findOne({
          name: 'Piso 21 - Puntos Suspensivos.mp3'
        }, function(err, result) {
          if (err) throw err;
          db.close();

          //STEP THREE

          fs.writeFile(result.name, result.file_data.buffer, function(err) {
            if (err) throw err;
            console.log(result);
          });
        });
      });
      res.render('audio');
    });
  

Третий шаг — это то, что я не знаю, что делать. Я хотел бы отправить result объект на audio.ejs страницу и каким-то образом предоставить audio tag доступ к нему без необходимости сохранять его в общедоступной папке, а затем удалять его после использования.

Что-то вроде этого,

ШАГ ТРЕТИЙ

   res.render('audio', result);
  

и каким-то образом предоставить audio tag доступ к нему на audio.ejs странице

Обновить

 let fs = require('fs');
var bodyParser = require('body-parser')
var urlencodedParser = bodyParser.urlencoded({ extended: false })

const MongoClient = require('mongodb');
const Binary = require('mongodb').Binary;
const ObjectId = require('mongodb').ObjectId;
const Grid = require('gridfs-stream');

const db = new MongoClient.Db('songs', new MongoClient.Server("localhost", 27017));
const gfs = Grid(db, MongoClient);

const bcrypt = require('bcryptjs');

module.exports = function(app){


    app.get('/audio/:filename', function (req, res) {

        MongoClient.connect("mongodb://localhost/songs", { useNewUrlParser: true }, function(err, db) {
            if (err) throw err;
            var dbo = db.db("songs");
            dbo.collection("song").findOne({name: req.params.filename}, function(err, result){
                if (err) throw err;
                db.close();
                const readstream = gfs.createReadStream(result.file_data);
                readstream.on('error', function (error) {
                    res.sendStatus(500);
                });
                console.log(res);
                res.type('audio/mpeg');
                readstream.pipe(res);
            });
        });
    });
  

Ответ №1:

На старинном жаргоне баз данных мультимедийные объекты называются BLOBS — двоичными большими объектами. В Mongo они обрабатываются с помощью подсистемы, известной как gridfs . Для упрощения этого есть хороший модуль npm под названием gridfs-stream.

Простой способ доставки медиаобъектов в браузеры — сделать их доступными по URL-адресам, которые выглядят как https://example.com/audio/objectname.mp3 . И они должны быть доставлены с соответствующим Content-Type заголовком для используемого кодека ( audio/mpeg для MP3). Тогда тег src может просто назвать URL-адрес, и все будет в порядке. Тег audio на странице браузера выглядит примерно так:

 <audio controls src="/audio/objectname.mp3" ></audio>
  

Итак, если вы хотите доставлять аудио напрямую через express, вам нужен маршрут с параметром, что-то вроде

  app.get('/audio/:filename', ...
  

Тогда программа node использует что-то подобное, не отлаженное!)

 const mongo = require('mongodb');
const Grid = require('gridfs-stream');
...
const db = new mongo.Db('yourDatabaseName', new mongo.Server("host", 27017));
const gfs = Grid(db, mongo);
...
app.get('/audio/:filename', function (req, res) {
   const readstream = gfs.createReadStream({filename: req.params.filename})
   readstream.on('error', function (error) {
        res.sendStatus(500)
   })
   res.type('audio/mpeg')
   readstream.pipe(res)
});
  

Это круто, потому что потоки — это круто: вашей узловой программе не нужно загружать весь аудиофайл в оперативную память. Аудиофайлы могут быть большими.

gridfs предлагает mongofiles утилиту командной строкиy для загрузки файлов в gridfs.

Но, учитывая все сказанное: большинство масштабируемых медиасервисов используют статические медиафайлы, доставляемые из файловых систем и / или сетей доставки контента. Такие серверы, как apache и nginx, многие годы программистов были потрачены на то, чтобы сделать доставку файлов быстрой и эффективной. В базе данных хранятся пути к файлам в CDN.

Как устранить неполадки такого рода?

  • Просмотрите журнал консоли браузера.
  • Перейдите по URL-адресу мультимедиа непосредственно из браузера. Посмотрите, что вы получите. Если он пустой, что-то не так с вашим кодом поиска.
  • В инструментах разработки в браузере посмотрите на вкладку Сеть (в Google Chrome). Найдите медиа-объект и изучите, что происходит.

Комментарии:

1. Действительно хороший ответ. Я пытался пока избегать gridfs, но это выглядит довольно понятно. Спасибо. Однако у меня есть несколько вопросов. Я предполагаю, что мне нужно сделать ajax-запрос на стороне клиента. если да, то что мне указать для расположения файла xhttp.open("GET", "file location", true); и так ли я указываю тип содержимого? xhttp.setRequestHeader("Content-type", "audio/mpeg");

2. src Атрибут в теге audio приведет к тому, что браузер получит ваш аудиофайл без необходимости в каком-либо сложном ajax. На вашем месте я бы сначала заставил это сработать.

3. Итак, я пытался заставить это работать, но у меня не получается. Я немного обновил его, чтобы он соответствовал моему существующему коду. Пожалуйста, взгляните. Я обновил свой вопрос. Я думаю, что ошибка в этой строке ` const db = new MongoClient. Db (‘песни’, новый MongoClient. Сервер («localhost», 27017));` . Имя моей базы данных — songs . и имя коллекции — song . Я не понимаю, как выполняется поиск в коллекции, просто введя имя базы данных.

4. Прочитайте материал о GridFS. Обратите внимание, что у него есть своя собственная схема индексации. Объекты, которые вы извлекаете с помощью GridFS, должны быть помещены туда тем же способом. Вот почему я упомянул mongofiles . Вы можете заменить приведенный мной пример кода для перехода на Mongo своим кодом, который работает.

5. В вашей ссылке mongofiles нет word. Не могли бы вы, пожалуйста, обновить его?

Ответ №2:

Я думаю, что то, что вы ищете, — это поток, чтобы вы могли передавать данные с сервера на веб-страницу напрямую, не сохраняя их. Node js поставляется с этой функциональностью, подробнее об этом из документации здесь https://nodejs.org/api/stream.html