2016-03-22 23 views
11

Vì vậy, bit của một vấn đề kỳ lạ. Tôi có một loạt các tập tin media được lưu dưới dạng chuỗi base64 trong Mongo, một số là hình ảnh, một số là video.Hiển thị video BASE64 với nút/express

tôi đã thực hiện một API để nhận được các tập tin media:

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

Bây giờ, hình ảnh không có vấn đề. Họ nạp tốt, cả trực tiếp từ API, và khi tôi gọi API từ một front-end (ví dụ <img src="/api/media/23498423">)

CÁC VẤN ĐỀ

Nếu tôi lấy một video từ một front-end, giống như hình ảnh - nhưng với một quay video hoặc đối tượng tag:

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

không có vấn đề, nhưng nếu tôi tải video trong trình duyệt trực tiếp từ API:

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

server proc ess crashes, không có lỗi. Nó chỉ đơn giản là đóng băng. Và chúng tôi không nói về các tệp video lớn - đó là video 1,5MB.

Loại phương tiện trong tiêu đề cho tất cả các video tôi đang thử nghiệm là video/mp4. Oh, và chỉ cần được rõ ràng: nếu tôi làm như vậy với hình ảnh, tất cả mọi thứ hoạt động hoàn hảo.

EDIT:

Được rồi, vì vậy theo đề nghị của @idbehold và @zeeshan tôi đã xem xét gridfs và gridfs-stream, và với mục đích ứng dụng của tôi, điều này chắc chắn là những gì tôi nên đã sử dụng ngay từ đầu. Tuy nhiên, sau khi triển khai gridfs trong ứng dụng của tôi, vấn đề vẫn tồn tại.

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

Khi tôi gọi tệp phương tiện (là hình ảnh hoặc video) từ giao diện người dùng, trong thẻ HTML, mọi thứ hoạt động tốt. Nhưng nếu tôi tải một video (một lần nữa, video nhỏ từ 1,5mb đến tối đa tổng kích thước 6mb) trực tiếp trong trình duyệt, quá trình máy chủ bị đóng băng. Để rõ ràng hơn một chút: Tôi đang thử nghiệm trên các cửa sổ và ứng dụng máy chủ (server.js) được chạy trong bảng điều khiển. Giao diện điều khiển và quá trình nó đang chạy là những gì bị đóng băng. Tôi không thể tải thêm bất kỳ trang/lượt xem nào trong ứng dụng nút và tôi thậm chí không thể dừng/tắt/tắt ứng dụng nút hoặc bảng điều khiển.

+0

Đối với tệp video 1,5MB, bây giờ bạn sẽ có bộ nhớ 3MB vào lúc bạn gọi 'res.end (tệp)'. Bạn nên phát video trực tiếp tới 'res' mà không bị giật. Bạn nên sử dụng một cái gì đó giống như GridFS của Mongo và API streaming của nó. Có thể bạn sẽ phải thêm hỗ trợ cho các yêu cầu phạm vi byte. – idbehold

+0

Tôi không biết gridfs, tôi sẽ có một cái nhìn, cảm ơn. –

+0

Vâng, [GridStore API] (https://github.com/mongodb/node-mongodb-native/blob/master/docs/gridfs.md) là những gì bạn sẽ muốn sử dụng. – idbehold

Trả lời

7

video streaming trực tiếp đến/từ GridFS sử dụng gridfs-stream hoặc với dụ db MongoDB bản địa hoặc 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); 
}); 

cho các tập tin hoàn chỉnh và dự án chạy:

Clone nút-lừa direct_upload_gridfs, chạy node app Tiếp theo npm install express mongodb gridfs-stream.

4

Thực sự là một vấn đề kỳ lạ ...
tôi có thể là đường tắt, nhưng nó có giá trị một shot:

Một trong những khác biệt khi mở một url trực tiếp từ trình duyệt là trình duyệt cũng sẽ cố gắng lấy http://localhost:8080/favicon.ico (trong khi cố gắng tìm biểu tượng tab).Có thể sự cố không liên quan đến mã video của bạn, mà là một số tuyến đường khác, cố gắng xử lý yêu cầu /favicon.ico?

Bạn đã thử sử dụng wget hoặc curl?

+0

Điều này đáng để xem xét. Cuộc gọi tốt. –

+0

Tôi đã làm một số thử nghiệm rộng rãi và trong không có trường hợp nào mà quá trình ứng dụng bị rơi là có bất kỳ vấn đề lấy favicon.ico - đó là một gợi ý tốt, vì vậy +1 cho rằng :) –

2

Tôi không biết câu trả lời, có thể đây là một gợi ý ngớ ngẩn, nhưng trình duyệt bạn đang sử dụng là gì? Có thể một cái gì đó từ Microsoft gây ra sự cố ...

+0

Tôi thử nghiệm trong chrome, firefox, firefox dev , opera, ie9 + 10, và cạnh với cùng một kết quả, cũng trên chrome android –

Các vấn đề liên quan