瀏覽器會根據多項輸入,決定顯示回應、下載回應,或將回應交給外部應用程式。Content-Disposition 提供強烈偏好,但內容類型、導覽情境、沙箱、瀏覽器能力與使用者設定也會影響結果。
Inline 與 Attachment 配置 #
Attachment 回應會要求下載:
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="guide.pdf"
Content-Length: 110352
X-Content-Type-Options: nosniffInline 回應允許在瀏覽器內呈現:
Content-Type: application/pdf
Content-Disposition: inline; filename="guide.pdf"inline 不保證會顯示。瀏覽器需要支援該媒體類型的檢視器,使用者也可以將某些類型設定為下載。省略標頭時,選擇主要交由媒體類型與導覽情境決定。
提供安全的檔名 #
filename 提供相容 ASCII 的後備值。filename* 使用 RFC 8187 定義的擴充參數編碼;它取代 RFC 5987,並能表示 Unicode:
Content-Disposition: attachment;
filename="report.pdf";
filename*=UTF-8''r%C3%A9sum%C3%A9.pdf請同時傳送兩個參數,因為較舊的用戶端可能忽略 filename*;當兩者都有效時,相容的接收者會優先使用 filename*。將伺服器提供的檔名視為不受信任輸入:
- 移除目錄分隔符號與控制字元。
- 拒絕將
.與..作為最終名稱。 - 讓預期副檔名與媒體類型一致。
- 設定合理的長度限制。
- 絕不要直接根據該值建立伺服器檔案系統路徑。
瀏覽器會各自清理檔名,因此不同實作的確切重新命名行為會有所差異。
內容類型與嗅探 #
Content-Type 描述表示內容。PDF 應為 application/pdf,SVG 應為 image/svg+xml,任意二進位資料應為 application/octet-stream。
X-Content-Type-Options: nosniffnosniff 會讓腳本與樣式擷取拒絕不相容的媒體類型,並限制其他受保護擷取路徑中以 MIME 為基礎的重新解讀。它不會修正錯誤的 Content-Type、使任意內容安全,或強制下載。以錯誤的無害類型提供主動內容仍是安全問題,因為導覽與嵌入規則同時取決於宣告的類型與請求情境。
HTML 下載連結 #
download 屬性表達連結的下載意圖:
<a href="/exports/report.csv" download="report.csv">Download report</a>對 HTTP(S) URL,瀏覽器只有在資源同源時才會遵循 download。blob: 與 data: URL 也符合資格;CORS 回應標頭不會使跨來源 HTTP URL 符合資格。回應的 Content-Disposition 檔名可能影響建議名稱,而 attachment 仍是跨來源下載可靠的伺服器端機制。授權必須保留在下載端點,因為將 URL 隱藏在按鈕後並不能保護它。
Blob URL 支援用戶端產生的檔案:
const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "report.csv";
document.body.append(link);
link.click();
link.remove();
setTimeout(() => URL.revokeObjectURL(url), 0);瀏覽器開始導覽後撤銷物件 URL,因為每個 URL 都會保留其後端資料。請從使用者發起的事件執行此序列;程式化點擊不會繞過瀏覽器下載政策。
自動化與安全限制 #
沙箱化框架需要 allow-downloads 沙箱權杖,而瀏覽器仍可能在沒有暫時使用者啟動或重複下載過於頻繁時封鎖下載。
跨來源隔離、彈出視窗政策、混合內容政策與企業設定可能引入額外限制。
在每個支援的瀏覽器中測試完整導覽:
- 驗證狀態、
Content-Type與Content-Disposition。 - 確認建議檔名與下載的位元組。
- 測試已驗證、重新導向與錯誤回應。
- 確認 HTML 錯誤頁面不會以受信任的副檔名儲存。
僅檢查標頭無法證明使用者可見的結果,因為瀏覽器會執行最終政策決策。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)