2016-03-22 15 views
11

したがって、奇妙な問題のビット。私はmongoのbase64文字列として保存されたメディアファイルをたくさん持っています。いくつかは画像であり、いくつかは動画です。私は、メディアファイルを取得するためのAPI作らノード/エクスプレスでBASE64ビデオを表示

:今

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を呼び出すとき

PROBLEM

(たとえば<img src="/api/media/23498423">のために)私は次のように、フロントエンドからの映像を取得した場合画像 - しかしビデオ - とまたはオブジェクトタグを:

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

そこには問題はないのですが、私はAPIから直接ブラウザでビデオをロードする場合:

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

サーバーprocはエッセークラッシュ、エラーなし。それは単に凍りつくだけです。そして、我々は巨大なビデオファイルについて話しているわけではありません。1.5MBのビデオです。

私がテストしているすべての動画のヘッダーのメディアタイプはvideo/mp4です。ああ、ちょうど明らかである:私がイメージで同じことをするなら、すべては完全に働く。

EDIT:

さて、@idbeholdと@zeeshanによって提案されたように、私はgridfsとgridfsストリームを見ていたし、私のアプリのために、これは確かに私が使用しているべきです最初はしかし、私のアプリで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); 
    }); 
}); 

HTMLタグ内のフロントエンドからメディアファイル(イメージまたはビデオ)を呼び出すと、すべて正常に機能します。しかし、ブラウザに直接ビデオをロードすると(合計サイズが1.5MBから最大6MBの小さなビデオも)、サーバープロセスがフリーズします。もう少し明確にするには:私はウィンドウズでテストしています。サーバーアプリケーション(server.js)はコンソールで実行されます。コンソールとそれが実行しているプロセスはフリーズしています。ノードアプリケーションでページ/ビューをもう読み込むことができず、ノードアプリケーションやコンソールを停止/強制終了することさえできません。

+0

1.5MBのビデオファイルの場合、 'res.end(file)'を呼び出すときに3MBのメモリが必要になります。バッファリングせずにビデオを 'res'にストリーミングする必要があります。あなたはMongoのGridFSとそのストリーミングAPIのようなものを使うべきです。おそらく、バイト範囲リクエストのサポートも追加する必要があります。 – idbehold

+0

私はグリフを知らなかった、私は一見、ありがとうございます。 –

+0

ええ、[GridStore API](https://github.com/mongodb/node-mongodb-native/blob/master/docs/gridfs.md)は使いたいものです。 – idbehold

答えて

7

ストリーミングビデオを直接に/使用GridFSからgridfs-streamいずれかMongoDBのネイティブDBインスタンスと又はマングース。完全なファイルのための

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

とプロジェクト実行中:

クローンdirect_upload_gridfsをノードカンニング、npm install express mongodb gridfs-stream続いnode appを実行します。本当に奇妙な問題

4

...
は、私は道オフかもしれないが、それはショットの価値がある:違いの

つのブラウザから直接URLを開くブラウザはまた、フェッチしようとするということですhttp://localhost:8080/favicon.ico(タブアイコンを見つけようとしている間)おそらく問題はあなたのビデオコードに関連するのではなく、むしろ/favicon.icoリクエストを処理しようとする別のルートにありますか?

wgetまたはcurlを試しましたか?

+0

これは調べる価値があります。いいですよ。 –

+0

私はいくつかの広範囲にわたるテストを行いましたが、アプリケーションプロセスがクラッシュした場合、favicon.icoを取得する際に問題はありませんでした。それは良い提案でした。そのため+1です:) –

2

私は答えを知らないのですが、これは愚かな提案ですが、使用しているブラウザは何ですか?おそらくマイクロソフトからの何かが問題を引き起こすかもしれません...

+0

chrome、firefox、firefox dev 、オペラ、ie9 + 10、同じ結果のエッジ、アンドロイドクロム –

関連する問題