2016-03-22 7 views
11

Also, ein bisschen ein seltsames Problem. Ich habe eine Reihe von Mediendateien als Base64 Strings in Mongo gespeichert, einige sind Bilder, einige sind Videos.Show BASE64 Video mit Knoten/Express

Ich habe eine API für das Erhalten der Mediendateien:

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

nun Bilder keine Probleme haben. Sie laden ganz gut, sowohl direkt von der API, und wenn ich die API von einem Front-End nennen (zum Beispiel <img src="/api/media/23498423">)

DAS PROBLEM

Wenn ich ein Video von einem Front-End holen, wie die Bilder - aber mit einem Video- oder Objekt-tag:

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

gibt es kein Problem, aber wenn ich das Video in einem Browser laden direkt von der API:

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

der Server proc Es stürzt ab, keine Fehler. Es friert einfach nur ein. Und wir sprechen nicht über riesige Videodateien - es ist ein 1,5 MB Video.

Der Medientyp in der Kopfzeile für alle Videos, die ich testen, ist video/mp4. Oh, und um es klar zu sagen: Wenn ich das gleiche mit Bildern mache, funktioniert alles perfekt.

EDIT:

Okay, so wie von @idbehold vorgeschlagen und @zeeshan ich gridfs einen Blick nahm und gridfs-Stream, und zum Zweck meiner app, das sicher ist, was ich verwendet habe, sollte an erster Stelle. Nach der Implementierung von Gridfs in meiner App besteht das Problem jedoch weiterhin.

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

Wenn ich die Mediendatei aufrufen (es Bild oder Video sein) von einem Front-End, innerhalb einer HTML-Tag, alles gut funktioniert. Aber wenn ich ein Video (wieder, kleinere Videos von 1.5mb bis maximal 6 MB Gesamtgröße) direkt im Browser laden, friert der Serverprozess ein. Um ein bisschen klarer zu sein: Ich teste gerade Windows, und die Server-App (server.js) wird in der Konsole ausgeführt. Die Konsole und der Prozess, der ausgeführt wird, frieren ein. Ich kann keine weiteren Seiten/Ansichten in der Knoten-App laden und kann die Knoten-App oder die Konsole nicht stoppen/beenden/beenden.

+0

Für eine 1,5 MB-Videodatei werden Sie jetzt 3 MB im Speicher haben, wenn Sie 'res.end (Datei)' aufrufen. Sie sollten das Video ohne Pufferung direkt in "res" streamen. Sie sollten etwas wie Mongos GridFS und seine Streaming-API verwenden. Sie müssen möglicherweise auch Unterstützung für Bytebereichsanforderungen hinzufügen. – idbehold

+0

Ich wusste nicht, gridfs, ich werde sehen, danke. –

+0

Ja, die [GridStore API] (https://github.com/mongodb/node-mongodb-native/blob/master/docs/gridfs.md) ist, was Sie verwenden möchten. – idbehold

Antwort

7

Streaming Videos direkt vom/GridFS mit gridfs-stream entweder mit mongodb-native db Instanz oder Mungo.

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

für komplette Dateien und laufenden Projekt:

Clone node-betrügen direct_upload_gridfs, laufen node app von npm install express mongodb gridfs-stream gefolgt.

4

wirklich ein seltsames Problem ...
konnte ich weg sein, aber es ist ein Versuch wert:

Einer der Unterschiede, wenn eine URL direkt aus dem Browser zu öffnen ist, dass der Browser auch zu holen versuchen http://localhost:8080/favicon.ico (beim Versuch, das Tab-Symbol zu finden).Vielleicht hängt das Problem nicht mit Ihrem Videocode zusammen, sondern eher mit einer anderen Route, die versucht, die Anfrage zu bearbeiten?

Haben Sie versucht mit wget oder curl?

+0

Dies ist eine Untersuchung wert. Guter Ruf. –

+0

Ich habe einige umfangreiche Tests und in keinem der Fälle, in denen der Bewerbungsprozess abgestürzt war gab es Probleme beim Abrufen von favicon.ico - es war ein guter Vorschlag, also +1 dafür :) –

2

Ich weiß nicht die Antwort, vielleicht ist dies ein dummer Vorschlag, aber was ist der Browser, den Sie verwenden? Vielleicht etwas von Microsoft verursacht das Problem ...

+0

Ich teste in Chrome, Firefox, Firefox-Dev , Opera, dh 9 + 10, und Kante mit dem gleichen Ergebnis, auch auf Android-Chrom –