首先聲明,這個(gè)問(wèn)題,只在IE6上會(huì)發(fā)生,IE8上是沒(méi)有此問(wèn)題的,IE7未測(cè)試。
IE6是一個(gè)很奇怪的東西,估計(jì)很多開(kāi)發(fā)人員對(duì)于IE6是非常頭疼的。貌似微軟一向喜歡弄這樣的幺蛾子,就像當(dāng)年的Microsoft JVM + Visual J++,雖然是好東西,但是由于未遵循標(biāo)準(zhǔn)規(guī)范,被Java組織給踢了出去,然后就不了了之了。
現(xiàn)在的應(yīng)用中,文件下載的功能是很常見(jiàn)的。通常的做法是,文件被存放在服務(wù)器的某個(gè)路徑,然后由應(yīng)用去讀取文件,再通過(guò)設(shè)置響應(yīng)頭來(lái)讓瀏覽器進(jìn)行響應(yīng)的動(dòng)作。如果希望瀏覽器能夠識(shí)別文件名,通常的做法是設(shè)置響應(yīng)頭中的Content-Disposition屬性:
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition", "attachment; filename=xxx.xls");
如果要能夠讓IE正確的處理中文文件名,則需要對(duì)中文文件名進(jìn)行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”。
通常,這種模式是沒(méi)有問(wèn)題的,但是如果文件名很長(zhǎng),就會(huì)出現(xiàn)“無(wú)法下載文件”的錯(cuò)誤。
經(jīng)過(guò)查找資料,在IE6上存在這樣的問(wèn)題,微軟的文檔(http://support.microsoft.com/kb/816868?LN=en-us)中說(shuō):
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.
也就是說(shuō),對(duì)于Content-Disposition這個(gè)響應(yīng)頭,IE6僅能處理150字節(jié)左右,再長(zhǎng)了就處理不了了。對(duì)于如何解決這個(gè)問(wèn)題,微軟的原文中也是閃爍其詞,說(shuō)是有一個(gè)Hotfix,但是又說(shuō)需要進(jìn)一步測(cè)試……
如何解決問(wèn)題呢?嘗試在Web上放置一個(gè)很長(zhǎng)中文名得文件,然后直接在IE6地址欄中輸入這個(gè)文件的全地址,下載、直接打開(kāi)都是正常的。因?yàn)檫@種情況下,服務(wù)器給出的響應(yīng)中不包含Content-Disposition段,估計(jì)是瀏覽器發(fā)現(xiàn)這是一個(gè)二進(jìn)制流,然后就將URL中后面的部分當(dāng)做文件名,所以文件名的處理都是瀏覽器在本地完成的,所以就避免了上面文檔中提到的BUG。(此處純屬猜想)
所以,解決的思路如下:
1. 在頁(yè)面上生成的附件鏈接中,包含附件的ID信息以及文件名。例如:<a href="/web/attachmentDownload/id/attachmentName.zip">附件</a>
2. 在服務(wù)器端做一個(gè)Servlet,映射到路徑 /attachmentDownload/*
3. Servlet獲取到請(qǐng)求的URL,解析出附件的ID信息及文件名
4. Servlet設(shè)置響應(yīng)頭 response.setContentType("application/octet-stream") ,或者設(shè)置成附件對(duì)應(yīng)的真實(shí)MIME-TYPE也可以。但是不設(shè)置Content-Disposition
5. 根據(jù)ID讀取文件,向響應(yīng)中寫入文件流
6. flush
測(cè)試了一下,是有效的一個(gè)辦法。但是為神馬覺(jué)得這個(gè)解決辦法奇怪的很?簡(jiǎn)直有點(diǎn)不像正常人類的思維方式了-_-|||
就這樣吧,神馬都是浮云!
posted on 2012-02-29 21:45
YODA 閱讀(1437)
評(píng)論(0) 編輯 收藏