3

我實現了一個簡單的文件上傳 - 下載機制。當用戶單擊文件名時,文件將使用這些HTTP標頭下載:文件下載(IE)時文件名損壞

HTTP/1.1 200 OK 
Date: Tue, 30 Sep 2008 14:00:39 GMT 
Server: Microsoft-IIS/6.0 
Content-Disposition: attachment; filename=filename.doc; 
Content-Type: application/octet-stream 
Content-Length: 10754 

我還支持日文文件名。爲了做到這一點,我編碼的文件名與該Java方法:

private String encodeFileName(String name) throws Exception{ 
    String agent = request.getHeader("USER-AGENT"); 
    if(agent != null && agent.indexOf("MSIE") != -1){ // is IE 
     StringBuffer res = new StringBuffer(); 
     char[] chArr = name.toCharArray(); 
     for(int j = 0; j < chArr.length; j++){ 
      if(chArr[j] < 128){ // plain ASCII char 
       if (chArr[j] == '.' && j != name.lastIndexOf(".")) 
        res.append("%2E"); 
       else 
        res.append(chArr[j]); 
      } 
      else{ // non-ASCII char 
       byte[] byteArr = name.substring(j, j + 1).getBytes("UTF8"); 
       for(int i = 0; i < byteArr.length; i++){ 
        // byte must be converted to unsigned int 
        res.append("%").append(Integer.toHexString((byteArr[i]) & 0xFF)); 
       } 
      } 
     } 
     return res.toString(); 
    } 
    // Firefox/Mozilla 
    return MimeUtility.encodeText(name, "UTF8", "B"); 
} 

它運作良好,到目前爲止,直到有人發現它不長文件名很好地工作。例如:あああああああああああああああ2008.10.1あ.doc。如果我將其中一個單字節點更改爲單字節下劃線,或者如果我刪除第一個字符,則它可以正常工作。即它取決於點字符的長度和URL編碼。 以下是一些例子。

這是打破(あああああああああああああああ2008.10.1あ.doc):

Content-Disposition: attachment; filename=%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%822008%2E10%2E1%e3%81%82.doc; 

這是OK(あああああああああああああああ2008_10.1あ.doc):

Content-Disposition: attachment; filename=%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%822008_10%2E1%e3%81%82.doc; 

這也是精(あああああああああああああああ2008.10.1あ.doc):

Content-Disposition: attachment; filename=%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%82%e3%81%822008%2E10%2E1%e3%81%82.doc; 

人有一個線索?

回答

6

gmail處理文件名的轉義有點不同:文件名被引用(雙引號),單字節句點不是URL轉義。 這樣,問題中的長文件名就可以了。

Content-Disposition: attachment; filename="%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%82%E3%81%822008.10.1%E3%81%82.doc" 

但是,文件名的字節長度(我認爲是一個bug)仍然存在一個限制(顯然只有IE)。因此,即使文件名僅由單字節字符組成,文件名的開頭也會被截斷。 該限制約爲160字節。

+0

恭喜!有時候,人們可以得到的最佳答案根本就沒有答案,這迫使我們再次審視這個問題 - 當你自己解決問題時,這會帶來更多的回報;) – 2008-09-30 15:49:49

+0

參見https://stackoverflow.com/q/93551/ 3995261('* = UTF-8''bit) – YakovL 2018-02-04 13:36:39

1

這裏的主要問題是,IE不支持相關的RFC,在這裏:RFC2231。見pointers and test cases。此外,您用於IE的解決方法(僅使用百分比轉義的UTF-8)還有其他一些問題;它可能不適用於所有語言環境(據我所知,除非IE配置爲始終在默認的URL中使用UTF-8,否則該方法在韓國將失敗),並且如前所述,存在長度限制(I聽說已在IE8中修復,但我還沒試試)。

+0

與此同時,IE支持RFC 6266中定義的編碼(從IE9開始) – 2012-12-16 13:03:53

2

如上所述,Content-Disposition和Unicode無法在沒有瀏覽器嗅探併爲每個瀏覽器返回不同標題的情況下運行所有​​主要瀏覽器。

我的解決方案是完全避免Content-Disposition標題,並將該文件名附加到URL的末尾,以誘使瀏覽器認爲它是直接獲取文件。例如

http://www.xyz.com/cgi-bin/dynamic.php/あああああああああああああああ2008.10.1あ.doc 

這自然會假定您在創建鏈接時知道文件名,儘管快速重定向標頭可以根據需要設置它。

+0

謝謝,這看起來不錯。下次我會試一試。 – Ovesh 2010-01-06 07:40:54

-2

我認爲這個問題在IE8中修復,我已經看到它在IE 8中工作。