S3 疑難雜症:只能下載無法顯示 index.html - Browser downloads html instead of serving
Amazon S3提供了許多功能,除了能儲存容量沒有限制之外,也能將 AWS 資源監控報告添加標籤儲存在S3 裡以利事後追蹤和報告,另一個常見用途就是能夠建立靜態網站。但明明照著說明進行設定、上傳檔案也變更存取權限和Policy,為什麼使用網站端點的時候會一直跳出視窗要我下載不知名的空白檔案呢?!
這個問題其實在於 index.html 檔案的 Content-Type 。
💡類似問題 #
AWS S3 的 Content-Type 是什麼? #
根據 AWS S3 的 Documentation:Content-Type 的定義如下:A standard MIME type describing the format of the contents. 一個用 MIME 定義內容格式的分類。
W3.org的說明有多幾個字:The Content-Type entity-header field indicates the media type of the entity-body sent to the recipient or, in the case of the HEAD method, the media type that would have been sent had the request been a GET.
當我們上傳檔案到 S3 Bucket 時,若沒有自行指定 Metadata 中的 Content-Type ,系統會將檔案的類型預設為 */octet-stream (ex: application/octet-stream 或 binary/octet-stream)。octet-stream 可以理解為格式不明、夾帶在網頁上的檔案,預設的動作就是讓使用者下載該檔案。因此瀏覽器才會一直跳出視窗要我們下載不知名的檔案。
這個問題一直都存在,有搜尋到2012年的論壇抱怨上傳檔案時總是出現錯誤的 Content-Type。沒遇到是運氣好,只能說2022年在官方的Documentation中還是沒有提醒大家要主動定義 Content-Type 也是有點sad。
💡相關文件說明: #
- 14.17 Content-Type - w3.org rfc2616
- PutObject > Content-Type - AWS Documentation S3 API Reference
- OCTET-STREAM File Type - file.org
- Content-Type for files uploaded via S3 automatically set to application/xml - GitHub
確認 Metadata 裡的 Content-Type #
有兩種方式可以確認物件的ContentType:
- 使用 AWS Management Console → S3 → Bucket → Object → Properties → Metadata
使用 AWS CLI 指令
head-object
:記得輸入自己的bucket名稱。$ aws s3api head-object --bucket subdomain.yourdomain.com --key index.html
得出的結果會像下方的 JSON格式,其中 “ContentType”: 應該要是 “txt/html”而不是”binary/octet-stream”。
{ "AcceptRanges": "bytes", "LastModified": "2022-01-26T09:57:39+00:00", "ContentLength": 12227, "ETag": "\"4xxxxxxxxxxxxxxxxxxxxxxxx8\"", "ContentType": "binary/octet-stream", "Metadata": {} }
💡 參考 #
如何變更 Content-Type ?有解嗎? #
避免出現這個問題的方式,是在上傳檔案時自定義 Content-Type。
$ aws s3api put-object --bucket subdomain.yourdomain.com --key index.html --body index.html --content-type txt/html
使用 AWS Management Console 變更 Content-Type #
在進入 S3 、進入指定的 Bucket 點選想要變更的物件 Object之後,在 Properties 分頁的最下方選擇編輯 Metadata 。預設的系統定義 System defined 之中 Value 並沒有 txt/html 的選項,這時候只能選 x 清除原本的設定自己輸入 txt/html 之後儲存變更就可以了。
使用 AWS CLI 變更 Content-Type #
AWS CLI 的指令中沒有直接變更設定的選項,因此可以使用「複製 cp」
- 將原本的檔案 s3://
/index.html 複製到同一個位址 s3:// /index.html - 使用 –content-type ‘txt/html’ 來覆蓋原有的設置
- –metadata-directive REPLACE 來讓S3強制執行變更 Metadata 的作業
$ aws s3 cp --content-type 'txt/html' s3://<bucket>/info s3://<bucket>/info
--metadata-directive REPLACE
💡 參考 #
- Working with object metadata - AWS Documentation
- How to change content type of Amazon S3 Objects - stackoverflow
- Changing S3 object content type through the AWS CLI - 2017
瀏覽器成功辨識物件格式,能正常瀏覽 #
因為目前使用S3的目的相對單純,可以個別進行設定或修正。若有需要對大量檔案的 Content-Type進行定義,歡迎參考以下的方式應對。