2016-03-03 6 views
13

पर जानकारी शामिल है aws-sdk मॉड्यूल और एक्सप्रेस 4.13 का उपयोग करके, एस 3 से कई तरीकों से प्रॉक्सी को प्रॉक्सी करना संभव है।एक्सप्रेस के साथ एस 3 से स्ट्रीमिंग फ़ाइल जिसमें लंबाई और फ़ाइल प्रकार

इसके लिए कॉलबैक संस्करण एक बफर, प्लस 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 

    }); 

} 

इस संस्करण के साथ समस्या आप है जो इसे भेजने से पहले पूरी फ़ाइल प्राप्त करने के लिए है कि, अच्छा नहीं, खासकर यदि यह वीडियो की तरह कुछ बड़ा है।

इस संस्करण में सीधे फ़ाइल स्ट्रीम होगा:

function(req,res){ 

    var s3 = new AWS.S3(); 

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

} 

लेकिन पहले के विपरीत, वह यह हेडर है, जो एक ब्राउज़र ठीक से फ़ाइल को संभालने के लिए आवश्यकता हो सकती है के बारे में कुछ नहीं करेंगे।

क्या एस 3 से सही शीर्षलेखों के माध्यम से गुज़रने, दोनों को स्ट्रीम के रूप में भेजने के लिए दोनों दुनिया के सर्वश्रेष्ठ प्राप्त करने का कोई तरीका है? इसे पहले मेटाडाटा प्राप्त करने के लिए HEAD एस 3 के अनुरोध के द्वारा किया जा सकता है, लेकिन क्या इसे एक एपीआई कॉल के साथ किया जा सकता है?

उत्तर

10

मेरी प्रोजेक्ट के लिए, मैं ऑब्जेक्ट मेटाडेटा को पुनर्प्राप्त करने के लिए केवल एक हेड ऑब्जेक्ट करता हूं (यह वास्तव में तेज़ है और ऑब्जेक्ट डाउनलोड करने से बचता है)। तब मैं जवाब में जोड़ने के सभी हेडर मैं पाइपिंग के लिए प्रचार करने के लिए की जरूरत है:

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

यह उत्कृष्ट है। धन्यवाद! – matthoiland

+0

तो आप एक के बजाय दो HTTP अनुरोध करना पसंद करते हैं? –

15

एक दृष्टिकोण httpHeaders घटना सुनने और यह के भीतर एक धारा पैदा कर रही है। आन्द्रे Werlang के जवाब पर

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

बिल्डिंग, हम एक forwardToExpress विधि के साथ एडब्ल्यूएस Request वस्तुओं बढ़ाने के लिए निम्नलिखित किया है:

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

फिर, हमारे मार्ग संचालकों में, हम कुछ इस तरह कर सकते हैं:

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

यह अनिवार्य रूप से हम क्या करते हैं। मैं सुझाव दूंगा कि हेडर का सेट जिसे आप प्रचार करना चाहते हैं (माना जाता है कि आप रेंज अनुरोधों और ईटैग आधारित क्लाइंट कैशिंग का समर्थन करना चाहते हैं) शायद: ['स्वीकार-श्रेणी', 'सामग्री-लंबाई', 'सामग्री-श्रेणी', 'सामग्री -प्रकार ',' etag ',' अंतिम संशोधित ']। – BobDickinson

संबंधित मुद्दे