将音频从 mongodb 传递到音频标签

passing audio from mongodb to audio tag

对于我的项目,我正在尝试创建一个音频播放器。存储文件的数据库方面对我来说是新的,因为我以前只存储过字符串。

到目前为止,我能做的是:

  1. 将音频文件存储到数据库中。(为了简单起见,我在这里链接到一个文件,但以后会上传)

  2. 将音频文件作为对象检索。

  3. 将音频文件存放在public文件夹中以备使用。

服务器端代码(路由代码与服务器代码分开)

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 访问权限,而不必将其保存在 public 文件夹中,然后必须使用后删除。

像这样,

第三步

  res.render('audio', result);

并以某种方式在 audio.ejs 页面

中授予对它的 audio tag 访问权限

更新

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);
            });
        });
    });

我想你要找的是一个流,这样你就可以把数据从服务器直接流到网页上而不用保存。 Node js 带有此功能,更多来自此处的文档 https://nodejs.org/api/stream.html

在过去的数据库术语中,媒体对象称为 BLOBS——二进制大对象。在 Mongo 中,它们使用 subsystem known as gridfs. There's a nice npm module called gridfs-stream 进行处理,以简化操作。

向浏览器传送媒体对象的一种简单方法是让它们在看起来像 https://example.com/audio/objectname.mp3 的 URL 后面可用。而且,它们应该与 appropriate Content-Type header for the codec in useaudio/mpeg 对于 MP3)一起交付。然后 src 标签可以简单地命名 URL 并且你正在摇摆不定。浏览器页面中的音频标签如下所示:

<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)
});

这很酷,因为流很酷:您的节点程序不需要将整个音频文件拖放到 RAM 中。音频文件可能很大。

gridfs 提供 mongofiles command line utility 用于将文件加载到 gridfs。

但是,话虽这么说:大多数可扩展媒体服务使用从文件系统 and/or 内容分发网络分发的静态媒体文件。像 apache 和 nginx 这样的服务器让程序员投入了很多年的时间来提高文件传输的速度和效率。数据库保存 CDN 中文件的路径名。

如何解决这种问题?

  • 查看浏览器的控制台日志。
  • 直接从浏览器访问媒体 URL。看看你得到了什么。如果为空,则说明您的检索代码有问题。
  • 在浏览器的开发工具中,查看“网络”选项卡(在 Google Chrome 中)。查找媒体对象,并检查发生了什么。