麻煩的下載對話方塊的中文檔案名稱處理.

來源:互聯網
上載者:User

因為不同瀏覽器對head處理的行為不同,所以下載對話方塊中的中文檔案名稱比較麻煩.沒有統一方法,不要以為你看到的是正確的中文,換個瀏覽器

或換個版本就不一定正確了.

 

大多數情況下,預設轉出UTF-8的字串是可以的:

 

String str = "這是一個UTF-8格式編碼的中文字串.dat";

如果不是UTF-8,那麼轉換到 UTF-8的字串,大多數時候是有效.

但是同樣是UTF-8字串,IE的不同版本看到的竟然是不同效果.雖然在contentTyep中已經指明 charset=UTF-8,而且從

用戶端進看頁面編碼也是UTF-8,但不同版本的IE卻有的亂碼有的正常.

 

對於IE而言,全部使用url-encode,所有版本都是正確的.這是網上流行的解決方案,但是.....................

對於IE6,限制檔案名稱大約在150個字元以內,一個中文字元UTF8編碼為3個byte,再URLEncode成9個byte,所以對於IE6最多不能超過17個中文.所以這個方法不行.

使用俺8年前用的IE下載的亂碼無敵大法,當時在IE6以下的所有版本都絕不亂碼.今天測試了一下,IE7,IE8,IE9BATE也堅決不亂,又不會有17個中文字元的限制.方法:

將字串以GB18030編碼轉換為byte[],然後將每個byte置的成char進行UTF8編碼:

byte[] src = "UTF8字串".getBytes("GB18030");

byte[] buf = new byte[src.length * 3];

int pos = 0;

for(int i=0;i<src.length;i++){

  char c = (char)src[i] & 0xFF;

  if(c <= 0x007F && c != 0) buf[pos++] = (byte)c;

  else if(c > 0x07FF){

     buf[pos+2] = (byte) (0x80 | ((c >> 0 ) & 0x3F));

     buf[pos+1] = (byte) (0x80 | ((c >> 6 ) & 0x3F));

     buf[pos+0] = (byte) (0xE0 | ((c >> 12 ) & 0x0F));

     pos += 3;

  }

  else{

 

     buf[pos+1] = (byte) (0x80 | ((c >> 0) & 0x3F));

     buf[pos+0] = (byte) (0xC0 | ((c >> 6 ) & 0x1F));

     pos += 2;

  }

}

 

return new String(buf,0,pos,"UTF-8");

絕對無敵....................

 

 

但是對於FF,url-encode肯定是不行了.直接輸出UTF-8,基本上測試過的版本都正確.

但是...................................

 

不同的容器行為又不樣.因為response.setCharacterEncoding只對實體起作用,對頭域不起作用,所以對於頭域只能手工處理.

比如tomcat,因為它預設是ISO8859_1,你通過response.setCharacterEncoding可以讓它對實體部分的處理按你指定的字元集

處理,但

response.setHeader("Content-Disposition","attachment;filename="+str);

無法控制str按指定的字元集處理,所以只能反向轉換把UTF-8轉成ISO8859_1:

 

str = new String(str.getBytes("UTF-8"),"ISO8859_1");

response.setHeader("Content-Disposition","attachment;filename="+str);

這樣在tomcat輸出後,大多數瀏覽器接收到的 byte[]是UTF-8格式的,能正確處理(IE還是存在版本問題),但這種方案又和容器偶合了.

如果FF不和容器偶合的話,可以進行base64編碼,就象IE進行urlencode編碼一樣.

我KAO,這不是折騰人嗎?

 

那麼要盡量做到通用,先要判斷瀏覽器:

String agent = request.getHeader("User-Agent");

if(agent == null) xxxx;

agent = agent.toUpperCase();

if(agent.indexOf("MSIE") != -1)   str = URLEncoder.encode(str);

else if(agent.indexOf("FIREFOX") != -1)   str = Base64Encoder.encode(str);

 

else{

............................

}

 

餘下的瀏覽器怎麼辦呢?經過測試Opera/Chrome都只能解釋UTF-8的中文名.所以

 

else{

............................

}將這樣:

 

else if(serverTyep.equals("tomcat")){

    str  = new String(str.getBytes("UTF-8"),"ISO8859_1");

 

}

else{

    //其它容器是否要轉碼看它預設用什麼字元集處理.比如resin就不用任何編碼,只要是UTF-8格式的就正確

}

 

對於服務端的不相容,其它平台不一定有這個問題.但是對於用戶端的不相容,任何平台都會有這個問題.要針對不同瀏覽器做不同的處理.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.