問題:
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