Android模擬 HTTP multipart/form-data 請求協議信息實現圖片上傳


問題:

Android應用中,當遇到填寫用戶信息、發表評論等操作,不可避免會遇到“form表單操作”(類似web form操作)上傳圖片的功能。

在這種情況下,使用Android的HTTPConnection/ ApacheHTTP 通過POST 和GET的方式就實現不了。

解決方法:


Android客戶端通過模擬 HTTP multipart/form-data 請求協議信息實現圖片上傳。

/** 
 * 文件名稱:UploadImage.java 
 * 
 * 版權信息:Apache License, Version 2.0 
 * 
 * 功能描述:實現圖片文件上傳。 
 * 
 * 創建日期:2011-5-10 
 * 
 * 作者:Bert Lee 
 */  
  
/* 
 * 修改歷史: 
 */  
public class UploadImage {  
    String multipart_form_data = "multipart/form-data";  
    String twoHyphens = "--";  
    String boundary = "****************fD4fH3gL0hK7aI6";    // 數據分隔符   
    String lineEnd = System.getProperty("line.separator");    // The value is "\r\n" in Windows.   
      
    /* 
     * 上傳圖片內容,格式請參考HTTP 協議格式。 
     * 人人網Photos.upload中的”程序調用“http://wiki.dev.renren.com/wiki/Photos.upload#.E7.A8.8B.E5.BA.8F.E8.B0.83.E7.94.A8 
     * 對其格式解釋的非常清晰。 
     * 格式如下所示: 
     * --****************fD4fH3hK7aI6 
     * Content-Disposition: form-data; name="upload_file"; filename="apple.jpg" 
     * Content-Type: image/jpeg 
     * 
     * 這兒是文件的內容,二進制流的形式 
     */  
    private void addImageContent(Image[] files, DataOutputStream output) {  
        for(Image file : files) {  
            StringBuilder split = new StringBuilder();  
            split.append(twoHyphens + boundary + lineEnd);  
            split.append("Content-Disposition: form-data; name=\"" + file.getFormName() + "\"; filename=\"" + file.getFileName() + "\"" + lineEnd);  
            split.append("Content-Type: " + file.getContentType() + lineEnd);  
            split.append(lineEnd);  
            try {  
                // 發送圖片數據   
                output.writeBytes(split.toString());  
                output.write(file.getData(), 0, file.getData().length);  
                output.writeBytes(lineEnd);  
            } catch (IOException e) {  
                throw new RuntimeException(e);  
            }  
        }  
    }  
      
    /* 
     * 構建表單字段內容,格式請參考HTTP 協議格式(用FireBug可以抓取到相關數據)。(以便上傳表單相對應的參數值) 
     * 格式如下所示: 
     * --****************fD4fH3hK7aI6 
     * Content-Disposition: form-data; name="action" 
     * // 一空行,必須有 
     * upload 
     */  
    private void addFormField(Set<Map.Entry<Object,Object>> params, DataOutputStream output) {  
        StringBuilder sb = new StringBuilder();  
        for(Map.Entry<Object, Object> param : params) {  
            sb.append(twoHyphens + boundary + lineEnd);  
            sb.append("Content-Disposition: form-data; name=\"" + param.getKey() + "\"" + lineEnd);  
            sb.append(lineEnd);  
            sb.append(param.getValue() + lineEnd);  
        }  
        try {  
            output.writeBytes(sb.toString());// 發送表單字段數據   
        } catch (IOException e) {  
            throw new RuntimeException(e);  
        }  
    }  
      
    /** 
     * 直接通過 HTTP 協議提交數據到服務器,實現表單提交功能。 
     * @param actionUrl 上傳路徑 
     * @param params 請求參數key為參數名,value為參數值 
     * @param files 上傳文件信息 
     * @return 返回請求結果 
     */  
    public String post(String actionUrl, Set<Map.Entry<Object,Object>> params, Image[] files) {  
        HttpURLConnection conn = null;  
        DataOutputStream output = null;  
        BufferedReader input = null;  
        try {  
            URL url = new URL(actionUrl);  
            conn = (HttpURLConnection) url.openConnection();  
            conn.setConnectTimeout(120000);  
            conn.setDoInput(true);        // 允許輸入   
            conn.setDoOutput(true);        // 允許輸出   
            conn.setUseCaches(false);    // 不使用Cache   
            conn.setRequestMethod("POST");  
            conn.setRequestProperty("Connection", "keep-alive");  
            conn.setRequestProperty("Content-Type", multipart_form_data + "; boundary=" + boundary);  
              
            conn.connect();  
            output = new DataOutputStream(conn.getOutputStream());  
              
            addImageContent(files, output);    // 添加圖片內容   
              
            addFormField(params, output);    // 添加表單字段內容   
              
            output.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);// 數據結束標志   
            output.flush();  
              
            int code = conn.getResponseCode();  
            if(code != 200) {  
                throw new RuntimeException("請求‘" + actionUrl +"’失敗!");  
            }  
              
            input = new BufferedReader(new InputStreamReader(conn.getInputStream()));  
            StringBuilder response = new StringBuilder();  
            String oneLine;  
            while((oneLine = input.readLine()) != null) {  
                response.append(oneLine + lineEnd);  
            }  
              
            return response.toString();  
        } catch (IOException e) {  
            throw new RuntimeException(e);  
        } finally {  
            // 統一釋放資源   
            try {  
                if(output != null) {  
                    output.close();  
                }  
                if(input != null) {  
                    input.close();  
                }  
            } catch (IOException e) {  
                throw new RuntimeException(e);  
            }  
              
            if(conn != null) {  
                conn.disconnect();  
            }  
        }  
    }  
      
    public static void main(String[] args) {  
        try {  
            String response = "";  
              
            BufferedReader in = new BufferedReader(new FileReader("config/actionUrl.properties"));  
            String actionUrl = in.readLine();  
              
            // 讀取表單對應的字段名稱及其值   
            Properties formDataParams = new Properties();  
            formDataParams.load(new FileInputStream(new File("config/formDataParams.properties")));  
            Set<Map.Entry<Object,Object>> params = formDataParams.entrySet();  
              
            // 讀取圖片所對應的表單字段名稱及圖片路徑   
            Properties imageParams = new Properties();  
            imageParams.load(new FileInputStream(new File("config/imageParams.properties")));  
            Set<Map.Entry<Object,Object>> images = imageParams.entrySet();  
            Image[] files = new Image[images.size()];  
            int i = 0;  
            for(Map.Entry<Object,Object> image : images) {  
                Image file = new Image(image.getValue().toString(), image.getKey().toString());  
                files[i++] = file;  
            }  
//            Image file = new Image("images/apple.jpg", "upload_file");   
//            Image[] files = new Image[0];   
//            files[0] = file;   
              
            response = new UploadImage().post(actionUrl, params, files);  
            System.out.println("返回結果:" + response);  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  

本篇文章來源於 Linux公社網站(www.linuxidc.com)  原文鏈接:http://www.linuxidc.com/Linux/2011-08/41944.htm


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM