中文名文件下載瀏覽器兼容處理

前言

文件下載功能中的文件名處理,這又是個老生長談的問題了,網絡上也有各類解決方式,但可能因爲各自項目語言以及編碼不一樣致使多數方案都不盡如人意,最近又遇到這個問題,姑且根據本身的環境和編碼總結一下java

後續觀點都是基於以下環境chrome

  • 服務端語言:JAVA
  • 項目編碼:GBK
  • 應用服務器Resin 3.1

分析

Firefox會截斷空格問題

在Firefox下,若是文件名中有空格,那麼空格後面部分的文字會被瀏覽器截取掉,客戶端獲取不到完整的文件名瀏覽器

解決方案:服務器

  1. 將文件名使用雙引號包裹起來
  2. 使用 MimeUtility.encodeWord(filename)方法,將其編碼爲「=?gb2312?B?xxxxxxxx?=」格式,其中的空格會被編碼掉,而且Firefox能夠識別該格式將其還原爲原始的文件名

IE6下請求頭長度有限制,文件名長度只能在150字節左右

通過測試,IE6下當要下載的文件名長度超過150字節後,超過部分會被瀏覽器截取掉(爲了保證擴展名完整,瀏覽器會從前面截取),而且若是是中文還有可能亂碼(應該是因爲編碼後再截取後不能再次還原爲中文字符),這個是IE6自身的機制,所以咱們只能考慮使用較短的文件名或者本身使用代碼合理將其截取網絡

關於亂碼

這一塊我也不是理解的十分透徹,就個人理解簡單分析一下:app

首先,你們都知道中文是多字節字符,因爲計算機的基本存儲單元是字節(byte),而一個byte顯然不可以表示包括中文在內的全部字符,所以中文、日文等等語言在存儲時都會被編碼爲多個字節存儲到計算機中,而後顯示時在相應解碼顯示便可。測試

而後,網絡傳輸的單位也是字節,所以java中的字符串在傳輸以前若是不進行手工編碼那麼會被默認按照操做系統的編碼格式進行編碼,到客戶端再按照默認格式解碼,若是都是中文環境一般沒有問題,可是若是兩邊的默認編碼不一致就比較容易致使編碼,所以仍是建議手動指定特定的編碼和解碼格式。編碼

而對於文件下載,客戶端不一樣瀏覽器識別的編碼也不一樣,可是基本上都識別UTF-8編碼以及ISO-8859-1編碼,後者firefox不能識別,而且若是文件名不是全中文還會致使被截斷,所以我仍是選擇採用UTF-8編碼spa

最後,貼上代碼

因爲其它功能都被拆分出去了,就不貼了,核心部分代碼都在這裏。操作系統

下面的代碼在IE6-九、firefox、chrome測試均可以正常下載

String us = request.getHeader("user-Agent");
if(ua!=null){
    ua = ua.toLowerCase();
    //IE6截取文件名避免亂碼
    if(ua.contains("msie 6")){
        //文件名中有空格,encode後會變成+,爲讓其正確顯示空格將其替換爲%20
     //getSubStr方法是根據字節數截取長度超過150字節後的字符 filename = URLEncoder.encode(getSubStr(filename),"utf-8").replaceAll("\\+","20%"); }else if(ua.contains("firefox")){ //編碼成 =?gb2312?B?xxxxxxxx?=的格式,firefox支持這種格式,這裏儘可能指定編碼類型,不然可能解析不了 filename = MimeUtility.encodeWord(filename,"utf-8","B");
response.setHeader("Content-disposition", "attachment; filename=\"+filename+\"");
    }else{
 filename = URLEncoder.encode(filename,"utf-8").replaceAll("\\+","20%"); } } response.setContentType("application/x-download;"); response.addHeader("Content-Disposition",filename) OutputStream out = response.getOutputStream(); out.write(contents); out.flush()

 

參考資料:http://stackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http

相關文章
相關標籤/搜索