Android類比 HTTP multipart/form-data 請求協議資訊實現圖片上傳
來源:互聯網
上載者:User
問題: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(); } } }