使用httpclient下載圖片時,url中含有中文字元,導致下載失敗的解決方法
先說解決方法吧:
修改tomcat的server.xml檔案,在Connector標籤中加上URLEncoding引數
<Connector port="8080" maxThreads="150" minSpareThreads="25"
maxSpareThreads="75" enableLookups="false" redirectPort="8443"
acceptCount="100" debug="99" connectionTimeout="20000"
disableUploadTimeout="true" URIEncoding="UTF-8"/>
原因:
經過分析,應該是Tomcat在解析引數的時候沒有使用正確的編碼格式(UTF-8)去解碼。
檢視$TOMCAT_HOME/webapps/tomcat-docs/config/http.html這個說明文件,有如下說明:
URIEncoding:This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.
也就是說,如果沒有設定URIEncoding, Tomcat預設是按ISO-8859-1進行URL解碼,ISO-8859-1並未包括中文字元,這樣的話中文字元肯定就不能被正確解析了。
如果包含中文,應當把中文字元變成位元組(利用GB18030或者UTF-8等編碼)。
客戶端轉換的方式必須和伺服器相同,比如伺服器認為URL中的中文按照UTF-8編碼,你的客戶端就不能按照GB18030編碼。
如果伺服器是你的,你應該知道它用哪種方法編碼URL。如果是Tomcat,你需要修改server.xml。上網用“tomcat URIEncoding”關鍵字搜尋,修改一個叫URIEncoding的東西。
客戶端,你可以構造一個java.net.URI(構造的時候會用UTF-8編碼),然後轉換成URL。也可咦用Apache HTTP Client中提供的方法進行轉義。
package com.zteits.atms.tgs.common.util; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.util.List; import org.apache.tools.zip.ZipEntry; import org.apache.tools.zip.ZipOutputStream; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.GetMethod; import com.zteits.atms.util.file.FileOperater; import flex.messaging.util.URLEncoder; public class DownLoadImgeUtil { /** * 生成檔案路徑 * @return * @throws Exception */ public static String getPath() throws Exception { int len = DownLoadImgeUtil.class.getResource("").getPath().indexOf("WEB-INF"); String filepath = DownLoadImgeUtil.class.getResource("").getPath().substring(0, len) + "picTemp"; FileOperater fo = new FileOperater(); fo.newFolder(filepath); return filepath; } /** * 下載圖片 * @param fileimgpath 檔名稱 * @param imageList 圖片路徑 * @return 是否下載成功 * @throws Exception */ public static int downLoadImge(String fileimgpath, List imageList) throws Exception { String filerootpath = getPath(); System.out.println("filerootpath: " + filerootpath); String filepath = filerootpath + "\\" + fileimgpath; System.out.println("filepath: " + filepath); OutputStream os = new FileOutputStream(filepath + ".zip"); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(os)); HttpClient hc = new HttpClient(); GetMethod getMethod = null; String filename1; try { for(int i = 0; i < imageList.size(); i++) { System.out.println("======== " + i); try { String fullURl = (String)imageList.get(i); //現場釋出的圖片路徑,支援中文 String strurl = tranformStyle(fullURl.substring(fullURl.lastIndexOf("$http")+1)); getMethod = new GetMethod(strurl); int randomNum = (int) (Math.random()*9000+1000); String path; path = fullURl.substring((fullURl.lastIndexOf(".")+1),fullURl.length()); // 重新命名 filename1 = fullURl.substring(0, (fullURl.lastIndexOf("$http")+1))+String.valueOf(randomNum)+"."+path; hc.executeMethod(getMethod); out.putNextEntry(new ZipEntry(filename1)); out.write(getMethod.getResponseBody()); // out.setEncoding("gbk"); } catch(Exception e) { e.printStackTrace(); } } // 釋放連線 getMethod.releaseConnection(); out.flush(); out.close(); } catch(Exception e) { e.printStackTrace(); } return 1; } /** * 下載圖片(根據路口分類放在不同資料夾) * @param fileimgpath 檔名稱 * @param imageList 圖片路徑 * @return 是否下載成功 * @throws Exception */ public static int downLoadImge1(String fileimgpath, List imageList) throws Exception { String filerootpath = getPath(); String filepath = filerootpath + "\\" + fileimgpath; OutputStream os = new FileOutputStream(filepath + ".zip"); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(os)); HttpClient hc = new HttpClient(); GetMethod getMethod = null; String filename1; try { for(int i = 0; i < imageList.size(); i++) { System.out.println("======== " + i); try { String fullURl = (String)imageList.get(i); //現場釋出的圖片路徑,支援中文 String strurl = tranformStyle(fullURl.substring(fullURl.lastIndexOf("$http")+1)); getMethod = new GetMethod(strurl); int randomNum = (int) (Math.random()*9000+1000); String path; path = fullURl.substring((fullURl.lastIndexOf(".")+1),fullURl.length());// .jpg // 重新命名 filename1 = fullURl.substring(0, (fullURl.lastIndexOf("$http")+1))+String.valueOf(randomNum)+"."+path; String fileCatergory = fullURl.substring(0,fullURl.indexOf("$")); hc.executeMethod(getMethod); File file =new File("\\" + fileCatergory); // 如果資料夾不存在建立資料夾,並且把圖片放入資料夾 if(!file.exists()){ file.mkdir(); URL url = new URL(strurl); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); InputStream is = conn.getInputStream(); byte[] buffer=new byte[1024]; int len=0; while((len=is.read(buffer))!=-1){ os.write(buffer, 0, len); } } out.putNextEntry(new ZipEntry(fileCatergory + "/" + filename1.trim())); out.write(getMethod.getResponseBody()); } catch(Exception e) { e.printStackTrace(); } } // 釋放連線 getMethod.releaseConnection(); out.flush(); out.close(); } catch(Exception e) { e.printStackTrace(); } return 1; } /** * 對中文字元進行UTF-8編碼 * @param source 要轉義的字串 * @return * @throws UnsupportedEncodingException */ public static String tranformStyle(String source) throws UnsupportedEncodingException { char[] arr = source.toCharArray(); StringBuilder sb = new StringBuilder(); for(int i = 0; i < arr.length; i++) { char temp = arr[i]; if(isChinese(temp)) { sb.append(URLEncoder.encode("" + temp, "UTF-8")); continue; } sb.append(arr[i]); } return sb.toString(); } /** * 獲取字元的編碼值 * @param s * @return * @throws UnsupportedEncodingException */ public static int getValue(char s) throws UnsupportedEncodingException { String temp = (URLEncoder.encode("" + s, "GBK")).replace("%", ""); if(temp.equals(s + "")) { return 0; } char[] arr = temp.toCharArray(); int total = 0; for(int i = 0; i < arr.length; i++) { try { int t = Integer.parseInt((arr[i] + ""), 16); total = total * 16 + t; } catch(NumberFormatException e) { e.printStackTrace(); return 0; } } return total; } /** * 判斷是不是中文字元 * @param c * @return */ public static boolean isChinese(char c) { Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); if(ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { return true; } return false; } }