Android应用中,当遇到填写用户信息、发表评论等操作,不可避免会遇到“form表单操作”(类似web form操作)上传图片的功能。
在这种情况下,使用Android的HTTPConnection/ ApacheHTTP 通过POST 和GET的方式就实现不了。
解决方法:
Android客户端通过模拟 HTTP multipart/form-data 请求协议信息实现图片上传。
1./**
2. * 文件名称:UploadImage.java
3. *
4. * 版权信息:Apache License, Version 2.0
5. *
6. * 功能描述:实现图片文件上传。
7. *
8. * 创建日期:2011-5-10
9. *
10. * 作者:Bert Lee
11. */
12.
13./*
1.
2. * 修改历史:
3. */
4.public class UploadImage {
5. String multipart_form_data = "multipart/form-data";
6. String twoHyphens = "--";
7. String boundary = "****************fD4fH3gL0hK7aI6"; // 数据分隔符
8. String lineEnd = System.getProperty("line.separator"); // The value is "\r\n" in Windows.
9.
10. /*
11. * 上传图片内容,格式请参考HTTP 协议格式。
12. * 人人网Photos.upload中的”程序调用“http://wiki.dev.renren.com/wiki/Photos.upload#.E7.A8.8B.E5.BA.8F.E8.B0.83.E7.94.A8
13. * 对其格式解释的非常清晰。
14. * 格式如下所示:
15. * --****************fD4fH3hK7aI6
16. * Content-Disposition: form-data; name="upload_file"; filename="apple.jpg"
17. * Content-Type: image/jpeg
18. *
19. * 这儿是文件的内容,二进制流的形式
20. */
21. private void addImageContent(Image[] files, DataOutputStream output) {
22. for(Image file : files) {
23. StringBuilder split = new StringBuilder();
24. split.append(twoHyphens + boundary + lineEnd);
25. split.append("Content-Disposition: form-data; name=\"" + file.getFormName() + "\"; filename=\"" + file.getFileName() + "\"" + lineEnd);
26. split.append("Content-Type: " + file.getContentType() + lineEnd);
27. split.append(lineEnd);
28. try {
29. // 发送图片数据
30. output.writeBytes(split.toString());
31. output.write(file.getData(), 0, file.getData().length);
32. output.writeBytes(lineEnd);
33. } catch (IOException e) {
34. throw new RuntimeException(e);
35. }
36. }
37. }
38.
39. /*
40. * 构建表单字段内容,格式请参考HTTP 协议格式(用FireBug可以抓取到相关数据)。(以便上传表单相对应的参数值)
41. * 格式如下所示:
42. * --****************fD4fH3hK7aI6
43. * Content-Disposition: form-data; name="action"
44. * // 一空行,必须有
45. * upload
46. */
47. private void addFormField(Set<Map.Entry<Object,Object>> params, DataOutputStream output) {
48. StringBuilder sb = new StringBuilder();
49. for(Map.Entry<Object, Object> param : params) {
50. sb.append(twoHyphens + boundary + lineEnd);
51. sb.append("Content-Disposition: form-data; name=\"" + param.getKey() + "\"" + lineEnd);
52. sb.append(lineEnd);
53. sb.append(param.getValue() + lineEnd);
54. }
55. try {
56. output.writeBytes(sb.toString());// 发送表单字段数据
57. } catch (IOException e) {
58. throw new RuntimeException(e);
59. }
60. }
61.
62. /**
63. * 直接通过 HTTP 协议提交数据到服务器,实现表单提交功能。
64. * @param actionUrl 上传路径
65. * @param params 请求参数key为参数名,value为参数值
66. * @param files 上传文件信息
67. * @return 返回请求结果
68. */
69. public String post(String actionUrl, Set<Map.Entry<Object,Object>> params, Image[] files) {
70. HttpURLConnection conn = null;
71. DataOutputStream output = null;
72. BufferedReader input = null;
73. try {
74. URL url = new URL(actionUrl);
75. conn = (HttpURLConnection) url.openConnection();
76. conn.setConnectTimeout(120000);
77. conn.setDoInput(true); // 允许输入
78. conn.setDoOutput(true); // 允许输出
79. conn.setUseCaches(false); // 不使用Cache
80. conn.setRequestMethod("POST");
81. conn.setRequestProperty("Connection", "keep-alive");
82. conn.setRequestProperty("Content-Type", multipart_form_data + "; boundary=" + boundary);
83.
84. conn.connect();
85. output = new DataOutputStream(conn.getOutputStream());
86.
87. addImageContent(files, output); // 添加图片内容
88.
89. addFormField(params, output); // 添加表单字段内容
90.
91. output.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);// 数据结束标志
92. output.flush();
93.
94. int code = conn.getResponseCode();
95. if(code != 200) {
96. throw new RuntimeException("请求‘" + actionUrl +"’失败!");
97. }
98.
99. input = new BufferedReader(new InputStreamReader(conn.getInputStream()));
100. StringBuilder response = new StringBuilder();
101. String oneLine;
102. while((oneLine = input.readLine()) != null) {
103. response.append(oneLine + lineEnd);
104. }
105.
106. return response.toString();
107. } catch (IOException e) {
108. throw new RuntimeException(e);
109. } finally {
110. // 统一释放资源
111. try {
112. if(output != null) {
113. output.close();
114. }
115. if(input != null) {
116. input.close();
117. }
118. } catch (IOException e) {
119. throw new RuntimeException(e);
120. }
121.
122. if(conn != null) {
123. conn.disconnect();
124. }
125. }
126. }
127.
128. public static void main(String[] args) {
129. try {
130. String response = "";
131.
132. BufferedReader in = new BufferedReader(new FileReader("config/actionUrl.properties"));
133. String actionUrl = in.readLine();
134.
135. // 读取表单对应的字段名称及其值
136. Properties formDataParams = new Properties();
137. formDataParams.load(new FileInputStream(new File("config/formDataParams.properties")));
138. Set<Map.Entry<Object,Object>> params = formDataParams.entrySet();
139.
140. // 读取图片所对应的表单字段名称及图片路径
141. Properties imageParams = new Properties();
142. imageParams.load(new FileInputStream(new File("config/imageParams.properties")));
143. Set<Map.Entry<Object,Object>> images = imageParams.entrySet();
144. Image[] files = new Image[images.size()];
145. int i = 0;
146. for(Map.Entry<Object,Object> image : images) {
147. Image file = new Image(image.getValue().toString(), image.getKey().toString());
148. files[i++] = file;
149. }
150.// Image file = new Image("images/apple.jpg", "upload_file");
151.// Image[] files = new Image[0];
152.// files[0] = file;
153.
154. response = new UploadImage().post(actionUrl, params, files);
155. System.out.println("返回结果:" + response);
156. } catch (IOException e) {
157. e.printStackTrace();
158. }
159. }
160.}
本篇文章来源于 Linux公社网站(www.linuxidc.com) 原文链接:http://www.linuxidc.com/Linux/2011-08/41944.htm