[关闭]
@coder-pig 2015-09-09T14:23:06.000000Z 字数 9361 阅读 2213

Android基础入门教程——7.3.1 Android 文件上传

Android基础入门教程


本节引言

本节和下一节文件下载一样,慎入...现在实际开发涉及文件上传不会自己写上传代码,一般
会集成第三网络库来做图片上传,比如android-async-http,okhttp等,另外还有七牛也提供
了下载和上传的API,喜欢的可以去官网查看相关的API文档!本节的话有兴趣看看就好!


1.项目用到的图片上传的关键方法:

思前想后,还是决定先贴下公司项目中用到的图片上传的核心方法,这里用到一个第三方的库:
android-async-http.jar,自己到github下下这个库~然后调用一下下面的方法即可,自己改下url!

上传图片的核心方法如下:

  1. private void sendImage(Bitmap bm)
  2. {
  3. ByteArrayOutputStream stream = new ByteArrayOutputStream();
  4. bm.compress(Bitmap.CompressFormat.PNG, 60, stream);
  5. byte[] bytes = stream.toByteArray();
  6. String img = new String(Base64.encodeToString(bytes, Base64.DEFAULT));
  7. AsyncHttpClient client = new AsyncHttpClient();
  8. RequestParams params = new RequestParams();
  9. params.add("img", img);
  10. client.post("http:xxx/postIcon", params, new AsyncHttpResponseHandler() {
  11. @Override
  12. public void onSuccess(int i, Header[] headers, byte[] bytes) {
  13. Toast.makeText(MainActivity.this, "Upload Success!", Toast.LENGTH_LONG).show();
  14. }
  15. @Override
  16. public void onFailure(int i, Header[] headers, byte[] bytes, Throwable throwable) {
  17. Toast.makeText(MainActivity.this, "Upload Fail!", Toast.LENGTH_LONG).show();
  18. }
  19. });
  20. }

2.使用HttpConnection上传文件:

简直卧槽...各种设置,各种麻烦...还是建议用1的方法吧,当然,实在太闲可以看看,
有轮子可用还是先别自己造轮子了...

  1. public class SocketHttpRequester
  2. {
  3. /**
  4. * 发送xml数据
  5. * @param path 请求地址
  6. * @param xml xml数据
  7. * @param encoding 编码
  8. * @return
  9. * @throws Exception
  10. */
  11. public static byte[] postXml(String path, String xml, String encoding) throws Exception{
  12. byte[] data = xml.getBytes(encoding);
  13. URL url = new URL(path);
  14. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
  15. conn.setRequestMethod("POST");
  16. conn.setDoOutput(true);
  17. conn.setRequestProperty("Content-Type", "text/xml; charset="+ encoding);
  18. conn.setRequestProperty("Content-Length", String.valueOf(data.length));
  19. conn.setConnectTimeout(5 * 1000);
  20. OutputStream outStream = conn.getOutputStream();
  21. outStream.write(data);
  22. outStream.flush();
  23. outStream.close();
  24. if(conn.getResponseCode()==200){
  25. return readStream(conn.getInputStream());
  26. }
  27. return null;
  28. }
  29. /**
  30. * 直接通过HTTP协议提交数据到服务器,实现如下面表单提交功能:
  31. * <FORM METHOD=POST ACTION="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-data">
  32. <INPUT TYPE="text" NAME="name">
  33. <INPUT TYPE="text" NAME="id">
  34. <input type="file" name="imagefile"/>
  35. <input type="file" name="zip"/>
  36. </FORM>
  37. * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,
  38. * 因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)
  39. * @param params 请求参数 key为参数名,value为参数值
  40. * @param file 上传文件
  41. */
  42. public static boolean post(String path, Map<String, String> params, FormFile[] files) throws Exception
  43. {
  44. //数据分隔线
  45. final String BOUNDARY = "---------------------------7da2137580612";
  46. //数据结束标志"---------------------------7da2137580612--"
  47. final String endline = "--" + BOUNDARY + "--/r/n";
  48. //下面两个for循环都是为了得到数据长度参数,依据表单的类型而定
  49. //首先得到文件类型数据的总长度(包括文件分割线)
  50. int fileDataLength = 0;
  51. for(FormFile uploadFile : files)
  52. {
  53. StringBuilder fileExplain = new StringBuilder();
  54. fileExplain.append("--");
  55. fileExplain.append(BOUNDARY);
  56. fileExplain.append("/r/n");
  57. fileExplain.append("Content-Disposition: form-data;name=/""+ uploadFile.getParameterName()+"/";filename=/""+ uploadFile.getFilname() + "/"/r/n");
  58. fileExplain.append("Content-Type: "+ uploadFile.getContentType()+"/r/n/r/n");
  59. fileExplain.append("/r/n");
  60. fileDataLength += fileExplain.length();
  61. if(uploadFile.getInStream()!=null){
  62. fileDataLength += uploadFile.getFile().length();
  63. }else{
  64. fileDataLength += uploadFile.getData().length;
  65. }
  66. }
  67. //再构造文本类型参数的实体数据
  68. StringBuilder textEntity = new StringBuilder();
  69. for (Map.Entry<String, String> entry : params.entrySet())
  70. {
  71. textEntity.append("--");
  72. textEntity.append(BOUNDARY);
  73. textEntity.append("/r/n");
  74. textEntity.append("Content-Disposition: form-data; name=/""+ entry.getKey() + "/"/r/n/r/n");
  75. textEntity.append(entry.getValue());
  76. textEntity.append("/r/n");
  77. }
  78. //计算传输给服务器的实体数据总长度(文本总长度+数据总长度+分隔符)
  79. int dataLength = textEntity.toString().getBytes().length + fileDataLength + endline.getBytes().length;
  80. URL url = new URL(path);
  81. //默认端口号其实可以不写
  82. int port = url.getPort()==-1 ? 80 : url.getPort();
  83. //建立一个Socket链接
  84. Socket socket = new Socket(InetAddress.getByName(url.getHost()), port);
  85. //获得一个输出流(从Android流到web)
  86. OutputStream outStream = socket.getOutputStream();
  87. //下面完成HTTP请求头的发送
  88. String requestmethod = "POST "+ url.getPath()+" HTTP/1.1/r/n";
  89. outStream.write(requestmethod.getBytes());
  90. //构建accept
  91. String accept = "Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*/r/n";
  92. outStream.write(accept.getBytes());
  93. //构建language
  94. String language = "Accept-Language: zh-CN/r/n";
  95. outStream.write(language.getBytes());
  96. //构建contenttype
  97. String contenttype = "Content-Type: multipart/form-data; boundary="+ BOUNDARY+ "/r/n";
  98. outStream.write(contenttype.getBytes());
  99. //构建contentlength
  100. String contentlength = "Content-Length: "+ dataLength + "/r/n";
  101. outStream.write(contentlength.getBytes());
  102. //构建alive
  103. String alive = "Connection: Keep-Alive/r/n";
  104. outStream.write(alive.getBytes());
  105. //构建host
  106. String host = "Host: "+ url.getHost() +":"+ port +"/r/n";
  107. outStream.write(host.getBytes());
  108. //写完HTTP请求头后根据HTTP协议再写一个回车换行
  109. outStream.write("/r/n".getBytes());
  110. //把所有文本类型的实体数据发送出来
  111. outStream.write(textEntity.toString().getBytes());
  112. //把所有文件类型的实体数据发送出来
  113. for(FormFile uploadFile : files)
  114. {
  115. StringBuilder fileEntity = new StringBuilder();
  116. fileEntity.append("--");
  117. fileEntity.append(BOUNDARY);
  118. fileEntity.append("/r/n");
  119. fileEntity.append("Content-Disposition: form-data;name=/""+ uploadFile.getParameterName()+"/";filename=/""+ uploadFile.getFilname() + "/"/r/n");
  120. fileEntity.append("Content-Type: "+ uploadFile.getContentType()+"/r/n/r/n");
  121. outStream.write(fileEntity.toString().getBytes());
  122. //边读边写
  123. if(uploadFile.getInStream()!=null)
  124. {
  125. byte[] buffer = new byte[1024];
  126. int len = 0;
  127. while((len = uploadFile.getInStream().read(buffer, 0, 1024))!=-1)
  128. {
  129. outStream.write(buffer, 0, len);
  130. }
  131. uploadFile.getInStream().close();
  132. }
  133. else
  134. {
  135. outStream.write(uploadFile.getData(), 0, uploadFile.getData().length);
  136. }
  137. outStream.write("/r/n".getBytes());
  138. }
  139. //下面发送数据结束标志,表示数据已经结束
  140. outStream.write(endline.getBytes());
  141. BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  142. //读取web服务器返回的数据,判断请求码是否为200,如果不是200,代表请求失败
  143. if(reader.readLine().indexOf("200")==-1)
  144. {
  145. return false;
  146. }
  147. outStream.flush();
  148. outStream.close();
  149. reader.close();
  150. socket.close();
  151. return true;
  152. }
  153. /**
  154. * 提交数据到服务器
  155. * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)
  156. * @param params 请求参数 key为参数名,value为参数值
  157. * @param file 上传文件
  158. */
  159. public static boolean post(String path, Map<String, String> params, FormFile file) throws Exception
  160. {
  161. return post(path, params, new FormFile[]{file});
  162. }
  163. /**
  164. * 提交数据到服务器
  165. * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)
  166. * @param params 请求参数 key为参数名,value为参数值
  167. * @param encode 编码
  168. */
  169. public static byte[] postFromHttpClient(String path, Map<String, String> params, String encode) throws Exception
  170. {
  171. //用于存放请求参数
  172. List<NameValuePair> formparams = new ArrayList<NameValuePair>();
  173. for(Map.Entry<String, String> entry : params.entrySet())
  174. {
  175. formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
  176. }
  177. UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, encode);
  178. HttpPost httppost = new HttpPost(path);
  179. httppost.setEntity(entity);
  180. //看作是浏览器
  181. HttpClient httpclient = new DefaultHttpClient();
  182. //发送post请求
  183. HttpResponse response = httpclient.execute(httppost);
  184. return readStream(response.getEntity().getContent());
  185. }
  186. /**
  187. * 发送请求
  188. * @param path 请求路径
  189. * @param params 请求参数 key为参数名称 value为参数值
  190. * @param encode 请求参数的编码
  191. */
  192. public static byte[] post(String path, Map<String, String> params, String encode) throws Exception
  193. {
  194. //String params = "method=save&name="+ URLEncoder.encode("老毕", "UTF-8")+ "&age=28&";//需要发送的参数
  195. StringBuilder parambuilder = new StringBuilder("");
  196. if(params!=null && !params.isEmpty())
  197. {
  198. for(Map.Entry<String, String> entry : params.entrySet())
  199. {
  200. parambuilder.append(entry.getKey()).append("=")
  201. .append(URLEncoder.encode(entry.getValue(), encode)).append("&");
  202. }
  203. parambuilder.deleteCharAt(parambuilder.length()-1);
  204. }
  205. byte[] data = parambuilder.toString().getBytes();
  206. URL url = new URL(path);
  207. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
  208. //设置允许对外发送请求参数
  209. conn.setDoOutput(true);
  210. //设置不进行缓存
  211. conn.setUseCaches(false);
  212. conn.setConnectTimeout(5 * 1000);
  213. conn.setRequestMethod("POST");
  214. //下面设置http请求头
  215. conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
  216. conn.setRequestProperty("Accept-Language", "zh-CN");
  217. conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
  218. conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
  219. conn.setRequestProperty("Content-Length", String.valueOf(data.length));
  220. conn.setRequestProperty("Connection", "Keep-Alive");
  221. //发送参数
  222. DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());
  223. outStream.write(data);//把参数发送出去
  224. outStream.flush();
  225. outStream.close();
  226. if(conn.getResponseCode()==200)
  227. {
  228. return readStream(conn.getInputStream());
  229. }
  230. return null;
  231. }
  232. /**
  233. * 读取流
  234. * @param inStream
  235. * @return 字节数组
  236. * @throws Exception
  237. */
  238. public static byte[] readStream(InputStream inStream) throws Exception
  239. {
  240. ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
  241. byte[] buffer = new byte[1024];
  242. int len = -1;
  243. while( (len=inStream.read(buffer)) != -1)
  244. {
  245. outSteam.write(buffer, 0, len);
  246. }
  247. outSteam.close();
  248. inStream.close();
  249. return outSteam.toByteArray();
  250. }
  251. }

偶然发现一篇以前转载的,可以搭配着上面的看看...:使用HttpConnection上传mp3文件


本节小结:

本节还是直接无视吧...关于文件上传等进阶部分直接教大家用第三方算了,项目中需要用到
第三方直接复制1的代码,导入个android-async-http即可!

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注