2016-03-22 12 views
11

Quindi, un piccolo problema. Ho un sacco di file multimediali salvati come stringhe base64 in mongo, alcuni sono immagini, alcuni sono video.Mostra video BASE64 con nodo/espresso

ho fatto un'API per ottenere i file multimediali:

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

Ora, le immagini non hanno problemi. Caricano bene, sia direttamente dalla API, e quando chiamo l'API da un front-end (per esempio <img src="/api/media/23498423">)

PROBLEMA

Se prelevo una video da un front-end, come la immagini - ma con un video-o object-tag:

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

non c'è nessun problema, ma se carico il video in un browser direttamente dal API:

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

server proc ess si blocca, nessun errore. Semplicemente si blocca. E non stiamo parlando di enormi file video: è un video da 1,5 MB.

Il tipo di supporto nell'intestazione per tutti i video con cui sto eseguendo il test è video/mp4. Oh, e tanto per essere chiari: se faccio lo stesso con le immagini, tutto funziona perfettamente.

EDIT:

Va bene, così come suggerito da @idbehold e @zeeshan ho preso uno sguardo al GridFS e GridFS-stream, e per lo scopo della mia app, questo è certamente quello che avrei dovuto usare innanzitutto. Tuttavia, dopo aver implementato gridfs nella mia app, il problema persiste.

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

Quando chiamo il file multimediale (sia esso immagine o video) da un front-end, all'interno di un tag HTML, tutto funziona bene. Ma se carico un video (di nuovo, video piccolissimi da 1.5mb a un massimo di 6mb di dimensione totale) direttamente nel browser, il processo del server si blocca. Per essere un po 'più chiaro: sto testando su Windows, e l'app del server (server.js) viene eseguita in console. La console e il processo in esecuzione è ciò che si blocca. Non riesco a caricare altre pagine/viste nell'app del nodo e non riesco nemmeno a interrompere/uccidere/arrestare l'app nodo o la console.

+0

Per un file video da 1,5 MB ora avrai 3MB in memoria nel momento in cui chiami 'res.end (file)'. Dovresti trasmettere il video direttamente a 'res' senza buffering. Dovresti usare qualcosa come GridFS di Mongo e la sua API di streaming. Probabilmente dovrai aggiungere anche il supporto per le richieste dell'intervallo di byte. – idbehold

+0

Non conoscevo la griglia, avrò un'occhiata, grazie. –

+0

Sì, [l'API GridStore] (https://github.com/mongodb/node-mongodb-native/blob/master/docs/gridfs.md) è ciò che vorrete usare. – idbehold

risposta

7

video in streaming direttamente da/per GridFS utilizzando gridfs-stream sia con MongoDB nativo DB di istanza o mangusta.

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

per i file completi e progetto in corso:

Clone nodo-cheat direct_upload_gridfs, gestita node app seguito da npm install express mongodb gridfs-stream.

4

Veramente un problema strano ...
potrei essere lontano, ma vale la pena un colpo:

Una delle differenze quando si apre un URL direttamente dal browser è che il browser cercherà anche di recuperare http://localhost:8080/favicon.ico (durante il tentativo di trovare l'icona della scheda).Forse il problema non è legato al tuo codice video, ma piuttosto a qualche altro percorso, cercando di gestire la richiesta /favicon.ico?

Hai provato a utilizzare wget o curl?

+0

Vale la pena esaminare. Buona chiamata –

+0

Ho fatto alcuni test approfonditi e in nessuno dei casi in cui il processo dell'applicazione si è bloccato ci sono stati problemi nel recupero di favicon.ico - era comunque un buon suggerimento, quindi +1 per quello :) –

2

Non conosco la risposta, forse questo è un suggerimento stupido, ma qual è il browser che stai utilizzando? Forse qualcosa da Microsoft causa il problema ...

+0

I test in chrome, firefox, firefox dev , opera, ossia 9 + 10 e bordo con lo stesso risultato, anche su Android Chrome –