问题:
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
*/

/package com.zjzcl;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

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(byte[] image, DataOutputStream output) {
StringBuilder split = new StringBuilder();
split.append(twoHyphens + boundary + lineEnd);
split.append("Content-Disposition: form-data; name=\"signImage\"; filename=\"c:/signImage.jpg\"" + lineEnd);
split.append("Content-Type: image/jpeg" + lineEnd);
split.append(lineEnd);
try {
// 发送图片数据
output.writeBytes(split.toString());
output.write(image, 0, image.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, byte[] 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();


byte[] files = null;

response = new UploadImage().post(actionUrl, params, files);
System.out.println("返回结果:" + response);
} catch (IOException e) {
e.printStackTrace();
}
}
}

更多相关文章

  1. Eclipse环境下格式化Android的代码风格
  2. android 格式化
  3. android常用数据库字段描述
  4. Android 文件格式
  5. 图解RGB565、RGB555、RGB16、RGB24、RGB32、ARGB32等格式的区别
  6. Android 基本控件及表单三大控件,事件处理
  7. android操作sqlite3的blob字段

随机推荐

  1. Android Google Map实例 - 在地图和卫星
  2. Ubuntu 14.04 LTS 安装 文泉驿微米黑 字
  3. WebView项目中PhoneGap插件使用细节start
  4. Android多媒体开发【10】-- android中Ope
  5. 用shape美化控件
  6. Android开发初步之Activity与Intent
  7. Android 最火快速开发框架AndroidAnnotat
  8. android应用安全――代码安全(android代码
  9. android之绕Y轴旋转
  10. android中handler案例