2016-08-29 7 views
0

Ich arbeite gerade an einem Webprojekt mit NodeJS, das Video-Upload und Player hat. Das Video hochgeladen wird in mongodb in binärer Form gespeichert werden, und wenn retrive es über API localhost/api/media /: id:Safari 9 kann HTML5-Video mit Binärquelle nicht wiedergeben?

/*getting media from db in binary format*/ 
res.setHeader('Accept-Ranges', 'bytes'); 
res.setHeader('Content-Range', 'bytes=0-1/' + media.length); 
res.setHeader('Content-Type', 'video/mp4'); 
res.setHeader('Cache-Control', 'public,max-age=0'); 
res.send(media); 

Diese funktionieren auf Chrome und Firefox, diese API gibt mir ein html5 Seite mit Video-Tag, das wie folgt aussehen:

<video controls="" autoplay="" name="media"> 
    <source src="localhost/api/media/abcde" type="video/mp4"> 
</video> 

die wie 7. auf ältere Safari fein sogar laufen aber auf Safari 9 insbesondere arbeitet es nicht und wird nur mit dem Text „Laden“, um die Mediensteuerung zeigen und kann Spiele niemals das Video. Ich versuche, die gleiche Videodatei in localhost zu legen und über localhost/test.mp4 darauf zuzugreifen, und das läuft in Safari 9 gut, so dass es kein Problem mit der Kodierung des Videos gibt. Irgendeine Idee, wie mache ich dieses eine Arbeit?

+0

Ihre 'Inhalt-Range' Antwort-Header sagen, dass Sie nur mit den ersten beiden Bytes antworten gehen von die Datei, aber dann schickst du die ganze Sache. Warum setzen Sie die Antwort-Header "Content-Range"? – idbehold

+0

Zuerst habe ich nichts anderes als Content-Type, und es funktioniert nicht, also habe ich das gelesen: http://stackoverflow.com/questions/32996396/safari-9-0-can-not-play-mp4- video-on-the-storage-server Und es hieß, dass Safari Browser nur nach den ersten 2 Bytes gefragt habe, also versuche ich zuerst mit Range = bytes = 0-1, und wenn es nicht funktioniert, habe ich es mit Content-Range versucht, nicht dass es anders wäre. Ich versuche auch mit "0-" + media.length + "/" + media.length, um die ganze Sache anzufordern, und es funktioniert auch nicht für mich. – Megazero

+0

Verwenden Sie GridFS? – idbehold

Antwort

0

Mit GridFS können Sie richtig die Datei auf dem Client mit Byte-Range-Support-Stream:

var db 
var app = require('express')() 
var parseRange = require('range-parser') 
var mongo = require('mongodb') 
var MongoClient = mongo.MongoClient 
var GridStore = mongo.GridStore 
var ObjectID = mongo.ObjectID 

function StreamGridFile(req, res, next, GridFile) { 
    res.setHeader('Accept-Ranges', 'bytes') 
    res.setHeader('Content-Disposition', 'filename="' + req.params.file + '"') 
    res.setHeader('Content-Type', GridFile.contentType) 
    var ranges = parseRange(GridFile.length, req.headers.range || '', { combine: true }) 
    if (Array.isArray(ranges) && ranges.length === 1 && ranges.type = 'bytes') { 
    var type = ranges.type 
    var start = ranges[0].start 
    var end = ranges[0].end 
    var total = end - start + 1 

    res.statusCode = 206 
    res.setHeader('Content-Range', 'bytes ' + start + '-' + end + '/' + GridFile.length) 
    res.setHeader('Content-Length', total) 

    return GridFile.seek(start, function() { 
     var finished = false 
     GridFile.stream(true).on('data', function (buff) { 
     if (finished) return; 
     var remaining = total 
     total -= buff.length 
     if (total <= 0) { 
      res.end(buff.slice(0, remaining)) 
      GridFile.close() 
      finished = true 
     } else { 
      res.write(buff) 
     } 
     }).on('end', function() { 
     if (finished) return; 
     finished = true 
     res.end() 
     }).on('error', next) 
    }) 
    } else if (ranges === -1) { 
    res.statusCode = 416 
    res.setHeader('Content-Range', 'bytes */' + GridFile.length) 
    return res.end() 
    } else { 
    res.statusCode = 200 
    res.setHeader('Content-Length', GridFile.length) 
    return GridFile.stream(true).pipe(res) 
    } 
} 

app.get('/files/get/:file', function (req, res, next) { 
    new GridStore(db, new ObjectID(req.params.file), null, 'r').open(function(err, GridFile) { 
    return GridFile ? StreamGridFile(req, res, next, GridFile) : res.send(404, 'Not Found') 
    }) 
}) 

MongoClient.connect("mongodb://localhost/test", function(err, database) { 
    if (err) throw err; 
    db = database; 
}) 
+0

Vielen Dank. Am Ende benutze ich stattdessen gridfs-stream, so dass mein Code am Ende anders aussieht, aber wenn ich deinen Code lese, wird mir klar, was eigentlich Byte-Range ist und wie Safari dazu benötigt wird. – Megazero

Verwandte Themen