[英]nodejs express serving folder and files stored in DigitalOcean/S3
[英]Serving files stored in S3 in express/nodejs app
我有應用程序用戶的照片是私人的。 我將照片(縮略圖也)存儲在AWS s3中。 網站中有一個頁面,用戶可以在其中查看他的照片(即縮略圖)。 現在我的問題是如何提供這些文件。 我評估的一些選項是:
我無法評估這兩個選項中哪一個是更好的選擇? 我想盡可能多地將工作重定向到S3或cloudfront,但即使使用了singed url也會首先向我的服務器發出請求。 我也想要緩存功能。
那么理想的做法是什么? 有關這些方法的特定問題的答案?
我會從S3流式傳輸它。 它非常簡單,簽名的URL要困難得多。 只需確保在將圖像上傳到S3時設置content-type
和content-length
標題。
var aws = require('knox').createClient({
key: '',
secret: '',
bucket: ''
})
app.get('/image/:id', function (req, res, next) {
if (!req.user.is.authenticated) {
var err = new Error()
err.status = 403
next(err)
return
}
aws.get('/image/' + req.params.id)
.on('error', next)
.on('response', function (resp) {
if (resp.statusCode !== 200) {
var err = new Error()
err.status = 404
next(err)
return
}
res.setHeader('Content-Length', resp.headers['content-length'])
res.setHeader('Content-Type', resp.headers['content-type'])
// cache-control?
// etag?
// last-modified?
// expires?
if (req.fresh) {
res.statusCode = 304
res.end()
return
}
if (req.method === 'HEAD') {
res.statusCode = 200
res.end()
return
}
resp.pipe(res)
})
})
如果您使用302 Found
將用戶重定向到已簽名的URL,則會根據其cache-control
標頭緩存生成的圖像,並且不會再次詢問它。
為防止瀏覽器緩存已簽名的URL本身,您應該發送適當的Cache-Control
標頭:
Cache-Control: private, no-cache, no-store, must-revalidate
因此,下次它會向原始網址發送請求,並將重定向到新簽名的網址。
您可以使用signedUrl
方法使用knox
生成簽名的URL。
但是不要忘記為每個上傳的圖像設置正確的標題。 我建議您同時使用Cache-Control
和Expires
標頭,因為某些瀏覽器不支持Cache-Control
標頭, Expires
允許您僅設置絕對過期時間。
使用第二個選項(通過您的應用程序流式傳輸圖像),您可以更好地控制情況。 例如,您將能夠根據當前日期和時間為每個響應生成Expires
標頭。
但速度怎么樣? 使用簽名的URL有兩個優點,可能會影響頁面加載速度。
首先,您不會使服務器過載。 如果快速生成簽名的URL,因為您只是哈希您的AWS憑據。 要通過服務器流式傳輸圖像,您需要在頁面加載期間保持大量額外連接。 無論如何,除非您的服務器是硬加載的,否則它不會產生任何實際差異。
其次,瀏覽器在頁面加載期間每個主機名只保留兩個並行連接。 因此,瀏覽器將在下載時保持並行解析圖像網址。 它還可以阻止從任何其他資源的下載下載圖像。
無論如何,要絕對確定你應該運行一些基准測試。 我的回答是基於我對HTTP規范的了解以及我在Web開發方面的經驗,但我從未試圖以自己的方式提供圖像。 直接從S3提供具有長緩存生命周期的公共圖像可以提高頁面速度,我相信如果你通過重定向來實現它,情況不會改變。
您應該記住,通過您的服務器流式傳輸圖像將帶來Amazon CloudFront的所有好處。 但只要您直接從S3提供內容,兩個選項都可以正常工作。
因此,在使用簽名網址時,有兩種情況應該加速您的網頁:
如果您在每個頁面上只有很少的圖像並直接從S3提供它們,您可能根本不會看到任何差異。
我運行了一些測試,發現我對緩存有誤。 確實,瀏覽器會緩存重定向到的圖像。 但它將緩存的圖像與重定向到的URL相關聯,而不是與原始圖像相關聯。 因此,當瀏覽器第二次加載頁面時,它再次從服務器請求圖像,而不是從緩存中獲取圖像。 當然,如果服務器使用相同的重定向URL響應它第一次響應,瀏覽器將使用其緩存,但簽名網址不是這種情況。
我發現強制瀏覽器緩存已簽名的URL以及它收到的數據可以解決問題。 但我不喜歡緩存無效重定向URL的想法。 我的意思是,如果瀏覽器以某種方式錯過圖像,它將嘗試使用緩存中的無效簽名URL再次請求它。 所以,我認為這不是一個選擇。
如果CloudFront更快地提供圖像或瀏覽器限制每個主機名的並行下載數量並不重要,使用瀏覽器緩存的優勢超出了通過服務器管道圖像的所有缺點。
看起來大多數社交網絡通過將其實際網址隱藏在某些私有代理后面來解決私有圖像的問題。 因此,他們將所有內容存儲在公共服務器上,但未經授權就無法獲取私有映像的URL。 當然,如果您在新標簽頁中打開私人圖片並將網址發送給您的朋友,他也可以看到圖片。 所以,如果它不適合你,那么你最好使用Jonathan Ong的解決方案 。
如果照片真的需要保密,我會擔心使用CloudFront選項。 您似乎可以更靈活地管理自己的安全策略。 我認為nginx設置可能比必要的更復雜。 Express應該作為遠程代理提供非常好的性能,它使用請求從S3獲取項目並將它們傳遞給授權用戶。 我強烈建議您查看Asset Rack,它使用哈希簽名在瀏覽器中啟用永久緩存。 您將無法使用默認機架,因為您需要計算每個文件的MD5(可能在上傳?),這是您在流式傳輸時無法做到的。 但是根據您的應用程序,它可以為您節省大量的工作量,因為瀏覽器永遠不需要重新獲取圖像。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.