首先聲明,這個問題,只在IE6上會發生,IE8上是沒有此問題的,IE7未測試。
IE6是一個很奇怪的東西,估計很多開發人員對于IE6是非常頭疼的。貌似微軟一向喜歡弄這樣的幺蛾子,就像當年的Microsoft JVM + Visual J++,雖然是好東西,但是由于未遵循標準規范,被Java組織給踢了出去,然后就不了了之了。
現在的應用中,文件下載的功能是很常見的。通常的做法是,文件被存放在服務器的某個路徑,然后由應用去讀取文件,再通過設置響應頭來讓瀏覽器進行響應的動作。如果希望瀏覽器能夠識別文件名,通常的做法是設置響應頭中的Content-Disposition屬性:
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition", "attachment; filename=xxx.xls");
如果要能夠讓IE正確的處理中文文件名,則需要對中文文件名進行UTF-8編碼:
response.addHeader("Content-Disposition", String.format("attachment;filename=%s", java.net.URLEncoder.encode("中文.xls", "UTF-8")));
編碼后的“中文.xls”為:“%E4%B8%AD%E6%96%87.xls”。
通常,這種模式是沒有問題的,但是如果文件名很長,就會出現“無法下載文件”的錯誤。
經過查找資料,在IE6上存在這樣的問題,微軟的文檔(http://support.microsoft.com/kb/816868?LN=en-us)中說:
This behavior occurs because the content disposition header for the file stream is greater than approximately 150 bytes and the Latin character set is equal to 150 characters. This behavior may occur if the content disposition header is formatted with a non-Latin character set, such as Japanese or Russian.
For example, a 17-character content disposition header in the Japanese character set is 153 bytes because the UTF-8 encoding scheme uses 9 bytes to represent a single Japanese character, but it uses only 1 byte in the Latin character set.
也就是說,對于Content-Disposition這個響應頭,IE6僅能處理150字節左右,再長了就處理不了了。對于如何解決這個問題,微軟的原文中也是閃爍其詞,說是有一個Hotfix,但是又說需要進一步測試……
如何解決問題呢?嘗試在Web上放置一個很長中文名得文件,然后直接在IE6地址欄中輸入這個文件的全地址,下載、直接打開都是正常的。因為這種情況下,服務器給出的響應中不包含Content-Disposition段,估計是瀏覽器發現這是一個二進制流,然后就將URL中后面的部分當做文件名,所以文件名的處理都是瀏覽器在本地完成的,所以就避免了上面文檔中提到的BUG。(此處純屬猜想)
所以,解決的思路如下:
1. 在頁面上生成的附件鏈接中,包含附件的ID信息以及文件名。例如:<a href="/web/attachmentDownload/id/attachmentName.zip">附件</a>
2. 在服務器端做一個Servlet,映射到路徑 /attachmentDownload/*
3. Servlet獲取到請求的URL,解析出附件的ID信息及文件名
4. Servlet設置響應頭 response.setContentType("application/octet-stream") ,或者設置成附件對應的真實MIME-TYPE也可以。但是不設置Content-Disposition
5. 根據ID讀取文件,向響應中寫入文件流
6. flush
測試了一下,是有效的一個辦法。但是為神馬覺得這個解決辦法奇怪的很?簡直有點不像正常人類的思維方式了-_-|||
就這樣吧,神馬都是浮云!