2013-11-09 67 views
4

我想這應該是一個簡單的事情Amazon S3的圖像,但我不能FING一個解決方案:■顯示從的NodeJS,expressjs和諾克斯

我想弄清楚的最佳途徑在網站上顯示存儲在亞馬遜S3上的圖像。

目前我正在試圖讓這個工作(不成功)

//app.js 
app.get('/test', function (req, res) { 
    var file = fs.createWriteStream('slash-s3.jpg'); 
    client.getFile('guitarists/cAtiPkr.jpg', function(err, res) { 
     res.on('data', function(data) { file.write(data); }); 
     res.on('end', function(chunk) { file.end(); }); 
    }); 
}); 

//index.html 
<img src="/test" /> 

是不是也許可以直接從亞馬遜的顯示圖像? 我的意思是,減輕服務器負載的解決方案將是最好的解決方案。

回答

9

這是streams的典型使用案例。您想要做的是:從Amazon S3請求文件,並將該請求的答案(即圖像)直接重定向到客戶端,而不存儲臨時文件。這可以通過使用流的.pipe()函數來完成。

我假定您用來查詢Amazon S3的庫返回一個流,因爲您已經使用了.on('data').on('end'),它們是流對象的標準事件。

這裏是你如何能做到這:

app.get('/test', function (req, res) { 
    client.getFile('guitarists/cAtiPkr.jpg', function(err, imageStream) { 
     imageStream.pipe(res); 
    }); 
}); 

通過使用管道,我們重定向到直接S3到客戶端的請求的輸出。當對S3的請求關閉時,這將自動結束快遞的res

有關流的更多信息,請參閱substack的優秀Stream Handbook。注意,在你的代碼片段中,你有兩個變量,名爲res:內部變量將掩蓋外部變量,這可能導致很難找到錯誤。

+0

謝謝!馬上工作。直接給客戶?完善!! – coiso

+1

您的服務器發出實際請求,但不會將結果存儲到文件,而是直接將輸出寫入客戶端套接字。這非常有效,並且可以進行簡潔的優化,請參閱流手冊以瞭解核心流式機制的概述。 –

+0

如何在流式傳輸多個圖像時應用此方法?例如,將許多圖像流式傳輸到像Facebook這樣的用戶新的Feed。 – c0mrade

6

如果您正確設置訪問控制(基於每個密鑰,而不是整個桶),那麼您可以使用<img src="http://aws.amazon.com/myBucket/myKey/moreKey.jpg">(或其他適當的域,如果您使用的東西不是us-east-1 )無論你想在你的HTML中顯示圖像。請記住,如果您希望瀏覽器顯示圖像,而不是在有人打開它時將圖像作爲附件下載,請設置MIME類型。

aws-sdk docs
s3: PUT Object docs

var AWS = require('aws-sdk'); 
AWS.config.update({ 
    accessKeyId: "something", 
    secretAccessKey: "something else", 
    region:'us-east-1', 
    sslEnabled: true, 
}); 
var fileStream = fs.createReadStream(filename); 
s3.putObject({ 
    Bucket:'myBucket', 
    Key: 'myKey/moreKey.jpg', 
    Body: fileStream, 
    ContentType:'image/jpeg', 
    ACL: 'public-read', 
}, function(err, data){ 
    if(err){ return callback(err) }; 
    console.log('Uploaded '+key); 
    callback(null); 
});