2016-03-03 25 views
13

Sử dụng mô-đun aws-sdk và Express 4.13, có thể ủy quyền tệp từ S3 theo một số cách.Tệp trực tuyến từ S3 với Express bao gồm thông tin về độ dài và loại tệp

phiên bản callback này sẽ trở lại cơ thể tập như một bộ đệm, cộng với tiêu đề có liên quan khác như Content-Length:

function(req,res){ 

    var s3 = new AWS.S3(); 

    s3.getObject({Bucket: myBucket, Key: myFile},function(err,data){ 

    if (err) { 
     return res.status(500).send("Error!"); 
    } 

    // Headers 
    res.set("Content-Length",data.ContentLength) 
     .set("Content-Type",data.ContentType); 

    res.send(data.Body); // data.Body is a buffer 

    }); 

} 

Vấn đề với phiên bản này là bạn phải có được toàn bộ tập tin trước khi gửi đi, đó là không tuyệt vời, đặc biệt nếu nó lớn như một video.

Phiên bản này sẽ trực tiếp dòng file:

function(req,res){ 

    var s3 = new AWS.S3(); 

    s3.getObject({Bucket: myBucket, Key: myFile}) 
    .createReadStream() 
    .pipe(res); 

} 

Nhưng không giống như người đầu tiên, nó sẽ không làm bất cứ điều gì về các tiêu đề, mà một trình duyệt có thể cần phải xử lý đúng đắn các tập tin.

Có cách nào để tận dụng tối đa cả hai thế giới, chuyển qua các tiêu đề chính xác từ S3 nhưng gửi tệp dưới dạng luồng không? Nó có thể được thực hiện bằng cách đầu tiên thực hiện một yêu cầu HEAD tới S3 để nhận siêu dữ liệu, nhưng nó có thể được thực hiện với một cuộc gọi API không?

Trả lời

10

Đối với dự án của mình, tôi chỉ cần thực hiện headObject để chỉ lấy siêu dữ liệu đối tượng (nó thực sự nhanh và tránh tải xuống đối tượng). Sau đó, tôi thêm vào phản ứng tất cả các tiêu đề tôi cần phải tuyên truyền cho đường ống:

var s3 = new AWS.S3(); 

    var params = { 
     Bucket: bucket, 
     Key: key 
    }; 
    s3.headObject(params, function (err, data) { 
     if (err) { 
      // an error occurred 
      console.error(err); 
      return next(); 
     } 
     var stream = s3.getObject(params).createReadStream(); 

     // forward errors 
     stream.on('error', function error(err) { 
      //continue to the next middlewares 
      return next(); 
     }); 

     //Add the content type to the response (it's not propagated from the S3 SDK) 
     res.set('Content-Type', mime.lookup(key)); 
     res.set('Content-Length', data.ContentLength); 
     res.set('Last-Modified', data.LastModified); 
     res.set('ETag', data.ETag); 

     stream.on('end',() => { 
      console.log('Served by Amazon S3: ' + key); 
     }); 
     //Pipe the s3 object to the response 
     stream.pipe(res); 
    }); 
+0

Điều này thật tuyệt vời. Cảm ơn! – matthoiland

+0

Vì vậy, bạn muốn thực hiện hai yêu cầu HTTP thay vì một yêu cầu? –

15

Một cách tiếp cận đang lắng nghe sự kiện httpHeaders và tạo ra một dòng suối bên trong nó.

s3.getObject(params) 
    .on('httpHeaders', function (statusCode, headers) { 
     res.set('Content-Length', headers['content-length']); 
     res.set('Content-Type', headers['content-type']); 
     this.response.httpResponse.createUnbufferedStream() 
      .pipe(res); 
    }) 
    .send(); 
4

Xây dựng về câu trả lời André Werlang, chúng tôi đã làm những điều sau đây để tăng thêm AWS Request đối tượng với một phương pháp forwardToExpress:

const _ = require('lodash'); 
const AWS = require('aws-sdk'); 

AWS.Request.prototype.forwardToExpress = function forwardToExpress(res, next) { 
    this 
    .on('httpHeaders', function (code, headers) { 
     if (code < 300) { 
      res.set(_.pick(headers, 'content-type', 'content-length', 'last-modified')); 
     }        
    }) 
    .createReadStream() 
    .on('error', next) 
    .pipe(res); 
};  

Sau đó, trong xử lý lộ trình của chúng tôi, chúng tôi có thể làm một cái gì đó như thế này:

s3.getObject({Bucket: myBucket, Key: myFile}).forwardToExpress(res, next); 
+0

Đây chính là những gì chúng tôi làm. Tôi khuyên bạn nên đặt tập hợp các tiêu đề bạn muốn truyền bá (giả sử bạn muốn hỗ trợ các yêu cầu phạm vi và bộ nhớ đệm trên máy khách dựa trên eTag): ['accept-range', 'content-length', 'content-range', 'content -loại ',' etag ',' được sửa đổi lần cuối ']. – BobDickinson

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