連結加了 download,點下去卻打開文字或圖片,沒有開始下載。先確認連結目標是否與頁面同源,再看最後一個 HTTP 回應。HTML 屬性提供下載用途,伺服器回應提供檔案與處理資訊,兩者不能互相代替。
這篇處理「點連結之後怎麼處理檔案」,不處理中文下載名稱的 UTF-8 編碼。連結能觸發下載,也還需要核對取得的是正確檔案,而不是登入頁或錯誤內容。
先比較頁面和檔案的來源
來源由協定、主機和連接埠組成。頁面在 https://example.com,檔案在 https://files.example.com,就是不同來源;同一主機換了連接埠,也不同。不要只看網址裡都有 example,就判定同源。
MDN 說明 download 適用於同源 URL,以及 blob、data 來源。它不能當成通用的「強制任何外站下載」指令。跨來源檔案能否下載,要看檔案端的回應與瀏覽器行為;網站也必須保留原有授權與存取規則。
<a href="/files/guide.txt" download="guide.txt">
下載檢查文件
</a>
這個相對路徑只有在實際解析到同源檔案時,才符合這種用途。若頁面使用另一個 base URL、連結被腳本改寫,或請求重新導向到資源主機,仍要核對瀏覽器最後到達的地址。
看完整請求,不只看連結的副檔名
開啟開發者工具的 Network,保留記錄後點連結,查看狀態碼、最終網址、Content-Type 與 Content-Disposition。檔名結尾是 zip,回應仍可能是 HTML 登入頁;文字檔回 200,也可能依回應設定直接在分頁中顯示。
若真正取得檔案的回應使用 Content-Disposition: attachment,它表達附件處理用途。同源連結的 download 和伺服器附件回應,是可以分別提供下載用途的方式,不代表任何一種都能控制訪客的儲存位置或所有瀏覽器設定。
Content-Type: text/plain; charset=utf-8
Content-Disposition: attachment; filename="guide.txt"
這裡只用簡單 ASCII 名稱,目的是看下載行為。若檔案能存下來、只有中文名稱亂碼,另查 Content-Disposition 的檔名參數與編碼;不必為了名稱問題修改跨來源規則。
本例同一份內容,三個入口
我們建立兩個只提供合成文件的本機 HTTP 來源,分別使用 8921 和 8922 連接埠。連結頁放在 8921,三個檔案入口回傳相同文字位元組。先固定內容,再觀察來源和附件回應的差異。
第一個連結指向同源的文字檔,帶 download 屬性。在本例 Chromium 中,點擊產生下載事件,取得建議名稱 local-guide.txt。第二個指向 8922 的文字檔,也帶 download,但回應沒有附件標頭;點擊後瀏覽器導向那個地址,直接顯示文字。
第三個仍指向 8922,但檔案回應加入附件標頭。這次 Chromium 產生下載事件,採用回應中的 server-guide.txt。保存第一與第三份文件後核對雜湊,內容一致,差別在連結來源和回應用途。
同源 + download:本例產生下載
跨來源 + download + 普通文字回應:本例在分頁顯示
跨來源 + 附件回應:本例產生下載
三個回應:檔案內容相同
這是同一版本 Chromium 在隔離案例中的結果。瀏覽器、使用者設定和檔案類型都可能影響後續處理;可能詢問、直接保存或開啟相關程式,不能從本例保證所有訪客都會看到同一個下載視窗。
判斷應修改連結端,還是檔案端
檔案就在你控制的同源網站,先確認連結真的指向該檔案,以及 download 是否出現在渲染後的 a 元素。若點擊被腳本攔截,查它有沒有另外導航、開分頁或取消原本行為;只修改原始模板還不足以知道訪客實際點到什麼。
檔案在你控制的獨立資源主機,則由真正送檔的服務設定合適的附件回應。不要只在連結頁追加更多屬性,希望它覆寫另一台伺服器的處理方式。改動前保存原設定,在一個合成檔案入口確認,再擴大到正式下載。
檔案屬於外部服務時,先使用該服務提供的合法下載入口與授權方式。不要把外站內容搬到自己的代理來繞過限制,也不要建議關閉瀏覽器安全設定。沒有控制檔案端的權限時,保留請求與回應資料交給服務維護者。
CORS 不等於 download 的同源條件
CORS 主要處理程式跨來源讀取回應的許可,不能把它與 HTML download 的適用條件混為一談。加入一個 CORS 標頭,不表示連結屬性就能強迫跨來源檔案保存。普通導覽、腳本讀取和下載用途各自有自己的規則。
如果功能本來需要由程式取得自有資料再產生 blob,先依資料來源的授權、CORS 和容量安排實作。不要為了下載一個大檔,就無條件把整份內容載入記憶體;也不能用 blob 這個名詞替代實際取得資料的權限。
最後核對內容與失敗入口
用一個可辨認的合成小檔案測試,保留來源網址、下載事件或導覽結果,以及最後回應的標頭。保存後再看內容與容量,確認不是錯誤頁被命名成文件。若需要會員驗證,也用自己的測試帳號核對合法與未授權兩種請求。
遇到 403、404 或登入轉向,先處理相應的存取或路徑問題,不靠 download 隱藏它。恢復正常檔案回應後,再在網站支援的瀏覽器確認處理方式。連結文字可以清楚寫檔案類型與用途,但不要承諾替訪客指定電腦上的完整儲存路徑。

評論0