1. 程式人生 > >使用httpclient下載圖片時,url中含有中文字元,導致下載失敗的解決方法

使用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;

    }

}