Показать видео 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 вызывает проблему...