如何在不同瀏覽器下載正確的檔案名稱(Content-Disposition)

先說明一下,本篇文章的背景。 某天前端工程師跑來問我,我在IE和Chrome下載檔案,檔案的名稱都是正確的,但在Safari下載的檔案名稱是錯誤的。 你可以幫我看一下Response-hearder 中 Content-Disposition的哪邊有問題嗎?

當時候的我,其實還不清楚他所說的 Content-Disposition 是什麼,關係到哪些問題,所以就開始了一連串的尋找如何下載正確檔案的名稱之旅。正所謂前人種樹,後人乘涼,其實早在之前,前人就已經將Content-Disposition設定好了,所以我不必處理這個部分。但最近才發現在某些瀏覽器下無法瀏覽正確檔名,所以我才有機會了解Content-Disposition是什麼,且影響了哪些部分。

先簡單介紹一下Content-Disposition,Content-Disposition是 MIME 協議的擴展,MIME 協議指示 MIME 用戶代理如何顯示附加的文件。所以Content-Disposition可以控制使用者儲存檔案時的檔案名稱。

所以了解了Content-Disposition的作用後,我就必需找出該如何設定,才能讓檔案在各種不同的瀏覽器被下載時,能顯示正確的檔案名稱。於是google到了以下的作法(程式取自於http://my.oschina.net/jsan/blog/180333)

var filename = ‘Nodejs中文指南.pdf’;var userAgent = (req.headers[‘user-agent’]||’’).toLowerCase();
if(userAgent.indexOf(‘msie’) >= 0 || userAgent.indexOf(‘chrome’) >= 0) {
  res.setHeader(‘Content-Disposition’, ‘attachment; filename=’ + encodeURIComponent(filename));
} else if(userAgent.indexOf(‘firefox’) >= 0) {
  res.setHeader(‘Content-Disposition’, ‘attachment; filename*=”utf8\’\’’ + encodeURIComponent(filename)+’”’);
} else {
res.setHeader(‘Content-Disposition’, ‘attachment; filename=’ + new Buffer(filename).toString(‘binary’));
}

但這並不符合我的需求,因為我是將檔案上傳到AWS的s3上,所以我無法在檔案被下載時才判斷是使用哪個瀏覽器下載,我需要先將資料設定好才行。於是又往其他方向找詢答案,並找到了以下的作法。

Content-Disposition: attachment;
filename=”$encoded_fname”;
filename*=utf-8'’$encoded_fname

原來當初Content-Dispostion 還不是正式標準的一部分,只是因為廣泛使用而從MIME標準中借過來而已,所以較少瀏覽器支援,但隨著時代的改變,便有了正式的規則去處理Content-Dispostion,新的方式只要使用filename*,大部份的瀏覽器就會優先使用filename*。此時下載檔案,就能確有正確的檔案名稱了。

更詳細的介紹可以參考正确处理下载文件时HTTP头的编码问题(Content-Disposition) 內文說的非常詳細!也期許自己能有一天,寫出一篇這麼詳細的文章!

Like what you read? Give Elsa Wang a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.