
文章插圖
Web 開(kāi)發(fā)過(guò)程中,相信大家都遇到過(guò)附件下載的場(chǎng)景,其中,各瀏覽器下載后的文件名中文亂碼問(wèn)題或許一度讓你苦惱不已 。
網(wǎng)上搜索一下,大部分都是通過(guò)Request Headers中的UserAgent字段來(lái)判斷瀏覽器類型,根據(jù)不同的瀏覽器做不同的處理,類似下面的代碼:
// MicroSoft Browserif (agent.contains("msie") || agent.contains("trident") || agent.contains("edge")) {// filename 特殊處理}// firefoxelse if (agent.contains("firefox")) {// filename 特殊處理}// safarielse if (agent.contains("safari")) {// filename 特殊處理}// Chromeelse if (agent.contains("chrome")) {// filename 特殊處理}// 其他else{ // filename 特殊處理}//最后把特殊處理后的文件名放到head里response.setHeader("Content-Disposition","attachment;fileName=" + filename);不過(guò),這樣的代碼看起來(lái)很魔幻,為什么每個(gè)瀏覽器的處理方式都不一樣?難道每次新出一個(gè)瀏覽器都要做兼容嗎?就沒(méi)有一個(gè)統(tǒng)一標(biāo)準(zhǔn)來(lái)約束一下這幫瀏覽器嗎?
帶著這個(gè)疑惑,我翻閱了 RFC 文檔,最終得出了一個(gè)優(yōu)雅的解決方案:
// percentEncodedFileName 為百分號(hào)編碼后的文件名response.setHeader("Content-disposition","attachment;filename=" + percentEncodedFileName +";filename*=utf-8''" + percentEncodedFileName);經(jīng)過(guò)測(cè)試,這段響應(yīng)頭可以兼容市面上所有主流瀏覽器,由于是 HTTP 協(xié)議范疇,所以語(yǔ)言無(wú)關(guān) 。只要按這個(gè)規(guī)則設(shè)置響應(yīng)頭,就能一勞永逸地解決惱人的附件名中文亂碼問(wèn)題 。
接下來(lái)課代表帶大家抽絲剝繭,通過(guò)閱讀 RFC 文檔,還原一下這個(gè)響應(yīng)頭的產(chǎn)出過(guò)程 。
1. Content-Disposition一切要從 RFC 6266 開(kāi)始,在這份文檔中,介紹了Content-Disposition響應(yīng)頭,其實(shí)它并不屬于HTTP標(biāo)準(zhǔn),但是因?yàn)槭褂脧V泛,所以在該文檔中進(jìn)行了約束 。它的語(yǔ)法格式如下:
content-disposition = "Content-Disposition" ":"disposition-type *( ";" disposition-parm )disposition-type= "inline" | "attachment" | disp-ext-type; case-insensitivedisp-ext-type= tokendisposition-parm= filename-parm | disp-ext-parmfilename-parm= "filename" "=" value| "filename*" "=" ext-value其中的disposition-type有兩種:
inline 代表默認(rèn)處理,一般會(huì)在頁(yè)面展示attachment 代表應(yīng)該被保存到本地,需要配合設(shè)置filename或filename*注意到disposition-parm中的filename和filename*,文檔規(guī)定:這里的信息可以用于保存的文件名 。
它倆的區(qū)別在于,filename 的 value 不進(jìn)行編碼,而filename*遵從 RFC 5987中定義的編碼規(guī)則:
Producers MUST use either the "UTF-8" ([RFC3629]) or the "ISO-8859-1" ([ISO-8859-1]) character set.由于filename*是后來(lái)才定義的,許多老的瀏覽器并不支持,所以文檔規(guī)定,當(dāng)二者同時(shí)出現(xiàn)在頭字段中時(shí),需要采用filename*,忽略filename 。
至此,響應(yīng)頭的骨架已經(jīng)呼之欲出了,摘錄 [RFC 6266] 中的示例如下:
Content-Disposition: attachment;filename="EURO rates";filename*=utf-8''%e2%82%ac%20rates這里對(duì)filename*=utf-8”%e2%82%ac%20rates做一下說(shuō)明,這個(gè)寫法乍一看可能會(huì)覺(jué)得很奇怪,它其實(shí)是用單引號(hào)作為分隔符,將等號(hào)右邊分成了三部分:第一部分是字符集(utf-8),中間部分是語(yǔ)言(未填寫),最后的%e2%82%ac%20rates代表了實(shí)際值 。對(duì)于這部分的組成,在RFC 2231.section 4 中有詳細(xì)說(shuō)明:
A single quote is used toseparate the character set, language, and actual value information inthe parameter value string, and an percent sign is used to flagoctets encoded in hexadecimal.2.PercentEncodePercentEncode 又叫 Percent-encoding 或 URL encoding.
正如前文所述,filename*遵守的是[RFC 5987] 中定義的編碼規(guī)則,在[RFC 5987] 3.2中定義了必須支持的字符集:
以上關(guān)于本文的內(nèi)容,僅作參考!溫馨提示:如遇健康、疾病相關(guān)的問(wèn)題,請(qǐng)您及時(shí)就醫(yī)或請(qǐng)專業(yè)人士給予相關(guān)指導(dǎo)!
「愛(ài)刨根生活網(wǎng)」www.malaban59.cn小編還為您精選了以下內(nèi)容,希望對(duì)您有所幫助:- 游戲地圖制作方法 手機(jī)游戲地圖制作軟件
- 性能完爆當(dāng)紅旗艦的二手手機(jī)如何選 性價(jià)比最高的二手旗艦手機(jī)
- 2000長(zhǎng)輩用性價(jià)比高的手機(jī) 2000左右高性價(jià)比手機(jī)老人用
- 這3款智能手機(jī) 這三款手機(jī)
- 如何解決手機(jī)卡的問(wèn)題 怎么辦才能解決手機(jī)卡的問(wèn)題
- 手機(jī)卡頓反應(yīng)慢 手機(jī)卡頓反應(yīng)慢怎么解決
- 購(gòu)買手機(jī)時(shí)配置如何選擇 買手機(jī)怎么選擇配置
- 你的手機(jī)屏幕究竟什么水平 手機(jī)屏幕什么樣
- 2021買手機(jī)內(nèi)存多大合適 2021年手機(jī)內(nèi)存多大合適
- 2022年買手機(jī)別只盯著旗艦,這十款性價(jià)比超高,是最合適你的選擇
