当前位置: 代码迷 >> Android >> 在 Android 上透过模拟 HTTP multipart/form-data 请求协议信息实现图片上传
  详细解决方案

在 Android 上透过模拟 HTTP multipart/form-data 请求协议信息实现图片上传

热度:80   发布时间:2016-04-28 06:59:06.0
在 Android 上通过模拟 HTTP multipart/form-data 请求协议信息实现图片上传

http://blog.csdn.net/jdsjlzx/article/details/8635884

通过构造基于 HTTP 协议的传输内容实现图片自动上传到服务器功能 。如果自己编码构造 HTTP 协议,那么编写的代码质量肯定不高,建议模仿?HttpClient?.zip?examples\mime\ClientMultipartFormPost.java 来实现,并通过源码来进一步理解如何优雅高效地构造 HTTP 协议传输内容。

?

?

?

自己构造 HTTP 协议传输内容的想法,从何而来呢?灵感启迪于这篇博文“Android下的应用编程——用HTTP协议实现文件上传功能?”,以前从未想过通过抓取 HTTP 请求数据格式,根据协议自己构造数据来实现数据提交。哎,Out 了。因为 Apache HttpClient 框架就是通过此方式来实现的,以前从未注意到,看来以后要多多向前人学习啊!结 果是:阅读了此框架的源码后,才知道自己编写的代码和人家相比真不是一个档次的。现在已经下定决心了,多读开源框架代码,不但可以熟悉相关业务流程,而且 还可以学到设计模式在实际业务需求中的应用,更重要的是领悟其中的思想。业务流程、实践能力、框架思想,一举三得,何乐而不为呢。^_^

?

?

?

test.html 部分源码:

?

<form action="Your_Action_Url?" method="post" enctype="multipart/form-data?" name="form1" id="form1">
? <p>
??? <label for="upload_file"></label>
??? <input type="file" name="upload_file" id="upload_file?" />
? </p>
? <p>
??? <input type="submit" name="action" id="action?" value="upload?" />
? </p>
</form>

?

通过 HttpWatch 查看抓取到的包数据格式:

?

通过 HttpWatch 查看抓取到的包数据格式

?

?

?

下面将分别通过按照 HttpWatch 抓取下来的协议格式内容构造传输内容实现文件上传功能和基于 HttpClient 框架实现文件上传功能。

?

项目配置目录Your_Project/config?,相关文件?如下:

?

actionUrl.properties 文件内容:

?

Your_Action_Url

?

formDataParams.properties 文件内容(对应 HTML Form 属性内容):

?

action?=upload

?

imageParams.properties 文件内容(这里文件路径已配置死了,不好!建议在程序中动态设置,即通过传入相关参数实现。):

?

upload_file?=images/roewe.jpg

?

MIMETypes.properties 文件内容(参考自?Multimedia MIME?Reference?):

?

jpeg:image/jpeg
jpg:image/jpeg
png:image/png
gif:image/gif

?

?

1. 在《Android下的应用编程——用HTTP协议实现文件上传功能?》代码的基础上,通过进一步改进得到如下代码(Java、Android 都可以 run):

?

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

2. 基于 HttpClient 框架实现文件上传,实例代码如下:

?

  1. /**?
  2. ?*?文件名称:ClientMultipartFormPost.java?
  3. ?*?
  4. ?*?版权信息:Apache?License,?Version?2.0?
  5. ?*?
  6. ?*?功能描述:通过?HttpClient?4.1.1?实现文件上传。?
  7. ?*?
  8. ?*?创建日期:2011-5-15?
  9. ?*?
  10. ?*?作者:Bert?Lee?
  11. ?*/??
  12. ??
  13. /*?
  14. ?*?修改历史:?
  15. ?*/??
  16. public?class?ClientMultipartFormPost?{??
  17. ????/**?
  18. ?????*?直接通过?HttpMime's?MultipartEntity?提交数据到服务器,实现表单提交功能。?
  19. [email protected]?
  20. ?????*/??
  21. ????public?static?String?filePost()?{??
  22. ????????HttpClient?httpclient?=?new?DefaultHttpClient();??
  23. ??????????
  24. ????????try?{??
  25. ????????????BufferedReader?in?=?new?BufferedReader(new?FileReader("config/actionUrl.properties"));??
  26. ????????????String?actionUrl;??
  27. ????????????actionUrl?=?in.readLine();??
  28. ????????????HttpPost?httppost?=?new?HttpPost(actionUrl);??
  29. ??????????????
  30. ????????????//?通过阅读源码可知,要想实现图片上传功能,必须将?MultipartEntity?的模式设置为?BROWSER_COMPATIBLE?。??
  31. ????????????MultipartEntity?multiEntity?=?new?MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);??
  32. //????????????MultipartEntity?multiEntity?=?new?MultipartEntity();??
  33. ??????????????
  34. ????????????//?读取图片的?MIME?Type?类型集??
  35. ????????????Properties?mimeTypes?=?new?Properties();??
  36. ????????????mimeTypes.load(new?FileInputStream(new?File("config/MIMETypes.properties")));??
  37. ??????????????
  38. ????????????//?构造图片数据??
  39. ????????????Properties?imageParams?=?new?Properties();??
  40. ????????????imageParams.load(new?FileInputStream(new?File("config/imageParams.properties")));??
  41. ????????????String?fileType;??
  42. ????????????for(Map.Entry<Object,Object>?image?:?imageParams.entrySet())?{??
  43. ????????????????String?path?=?image.getValue().toString();??
  44. ????????????????fileType?=?path.substring(path.lastIndexOf(".")?+?1);??
  45. ????????????????FileBody?binaryContent?=?new?FileBody(new?File(path),?mimeTypes.get(fileType).toString());??
  46. //????????????????FileBody?binaryContent?=?new?FileBody(new?File(path));??
  47. ????????????????multiEntity.addPart(image.getKey().toString(),?binaryContent);??
  48. ????????????}??
  49. ??????????????
  50. ????????????//?构造表单参数数据??
  51. ????????????Properties?formDataParams?=?new?Properties();??
  52. ????????????formDataParams.load(new?FileInputStream(new?File("config/formDataParams.properties")));??
  53. ????????????for(Entry<Object,?Object>?param?:?formDataParams.entrySet())?{??
  54. ????????????????multiEntity.addPart(param.getKey().toString(),?new?StringBody(param.getValue().toString()));??
  55. ????????????}??
  56. ??????????????
  57. ????????????httppost.setEntity(multiEntity);??
  58. //????????????Out.println("executing?request?"?+?httppost.getRequestLine());??
  59. ??????????????
  60. ????????????HttpResponse?response?=?httpclient.execute(httppost);??
  61. ????????????HttpEntity?resEntity?=?response.getEntity();??
  62. ??????????????
  63. //????????????Out.println("-------------------");??
  64. //????????????Out.println(response.getStatusLine());??
  65. ????????????if(resEntity?!=?null)?{??
  66. ????????????????String?returnContent?=?EntityUtils.toString(resEntity);??
  67. ????????????????EntityUtils.consume(resEntity);??
  68. ??????????????????
  69. ????????????????return?returnContent;?//?返回页面内容??
  70. ????????????}??
  71. ????????}?catch?(IOException?e)?{??
  72. ????????????e.printStackTrace();??
  73. ????????}?finally?{??
  74. ????????????//?释放资源??
  75. ????????????httpclient.getConnectionManager().shutdown();??
  76. ????????}??
  77. ????????return?null;??
  78. ????}??
  79. ??
  80. ????//?测试??
  81. ????public?static?void?main(String[]?args)?{??
  82. ????????Out.println("Response?content:?"?+?ClientMultipartFormPost.filePost());??
  83. ????}??
  84. ??
  85. }?

?

  相关解决方案