Показать видео BASE64 с помощью node/express

Итак, бит нечетной проблемы. У меня есть куча медиа файлов, сохраненных в виде строк base64 в mongo, некоторые из них - изображения, а некоторые - видео.

Я создал API для получения медиафайлов:

app.get('/api/media/:media_id', function (req, res) {
    media.findById(req.params.media_id)
        .exec(function (err, media) {
            if (err) {
                res.send(err);
            }

            var file = new Buffer(media.file, 'base64');
            res.writeHead(200, {'Content-Type': media.type, 'Content-Transfer-Encoding': 'BASE64', 'Content-Length': file.length});
            res.end(file);
        });
});

Теперь у изображений нет проблем. Они загружаются просто отлично, как непосредственно из API, так и когда я вызываю API из front-end (например <img src="/api/media/23498423">)

ПРОБЛЕМА

Если я получаю видео с интерфейсного интерфейса, например изображения, но с видео- или объектным тегом:

<video src="/api/media/3424525" controls></video>

нет проблем, но если я загружу видео в браузере непосредственно из API:

http://localhost:8080/api/media/3424525

происходит сбой сервера, никаких ошибок. Он просто замерзает. И мы не говорим о огромных видеофайлах - это 1,5 МБ видео.

Тип мультимедиа в заголовке для всех видео, которые я тестирую, составляет video/mp4. О, и просто чтобы быть ясным: если я делаю то же самое с изображениями, все работает отлично.

EDIT:

Хорошо, так, как это было предложено @idbehold и @zeeshan, я взглянул на gridfs и gridfs-stream, и с целью моего приложения это, безусловно, то, что я должен был использовать в первую очередь. Однако после внедрения gridfs в моем приложении проблема все еще сохраняется.

app.get('/api/media/:media_id', function (req, res) {
    gfs.findOne({ _id: req.params.media_id }, function (err, file) {
        if (err) {
            return res.status(400).send(err);
        }
        if (!file) {
            return res.status(404).send('');
        }

        res.set('Content-Type', file.contentType);
        res.set('Content-Disposition', 'inline; filename="' + file.filename + '"');

        var readstream = gfs.createReadStream({
            _id: file._id
        });

        readstream.on("error", function (err) {
            console.log("Got an error while processing stream: ", err.message);
            res.end();
        });

        readstream.pipe(res);
    });
});

Когда я вызываю мультимедийный файл (будь то изображение или видео) из front-end, в теге HTML все работает отлично. Но если я загружу видео (опять же, небольшие видеоролики размером от 1,5 до 6 макс.) Прямо в браузере, серверный процесс зависает. Быть немного более ясным: я тестирую на окнах, а серверное приложение (server.js) запускается в консоли. Консоль и выполняемый ею процесс замерзают. Я не могу загрузить больше страниц/представлений в приложение node, и я не могу даже остановить/убить/выключить приложение node или консоль.

Ответ 1

Потоковая передача видео непосредственно в/из GridFS с помощью gridfs-stream либо с помощью экземпляра mbodb-native db, либо mongoose.

var mongo = require('mongodb'),
    Grid = require('gridfs-stream'),
    db = new mongo.Db('yourDatabaseName', new mongo.Server("127.0.0.1", 27017)),
    gfs = Grid(db, mongo);

//store
app.post('/video', function (req, res) {
    req.pipe(gfs.createWriteStream({
        filename: 'file_name_here'
    }));
    res.send("Success!");
});

//get
app.get('/video/:vid', function (req, res) {
    gfs.createReadStream({
        _id: req.params.vid // or provide filename: 'file_name_here'
    }).pipe(res);
});

для полных файлов и запуска проекта:

Клон node -cheat direct_upload_gridfs, запустите node app, а затем npm install express mongodb gridfs-stream.

Ответ 2

Поистине странная проблема...
Я мог бы уйти, но это стоит того:

Одно из отличий при открытии URL-адреса непосредственно из браузера заключается в том, что браузер также попытается извлечь http://localhost:8080/favicon.ico (при попытке найти значок вкладки). Может быть, проблема не связана с вашим видеокодом, а скорее с каким-то другим маршрутом, пытаясь обработать запрос /favicon.ico?

Пробовали ли вы использовать wget или curl?

Ответ 3

Я не знаю ответа, может быть, это глупое предложение, но какой браузер вы используете? Возможно, что-то от Microsoft вызывает проблему...