HttpMime 处理 多部件 POST 请求
HttpMime 处理 多部件 POST 请求
在有的场合例如我们要用到上传文件的时候,就不能使用基本的GET请求和POST 请求了,我们要使用多部件的POST请求。由于Android 附带的 HttpClient 版本暂不支持多部件 POST 请求,所以我们需要用到一个 HttpMime 开源项目,该组件是专门处理与 MIME 类型有关的操作。因为 HttpMime 是包含在 HttpComponents 项目中的,所以我们需要去 apache 官方网站下载 HttpComponents,然后把其中的HttpMime.jar 包放到项目中去。
1 package com.scott.http; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.InputStream; 5 6 import org.apache.http.HttpResponse; 7 import org.apache.http.HttpStatus; 8 import org.apache.http.client.HttpClient; 9 import org.apache.http.client.methods.HttpGet; 10 11 import android.app.Activity; 12 import android.os.Bundle; 13 import android.view.View; 14 import android.widget.Button; 15 import android.widget.Toast; 16 17 public class HttpActivity extends Activity { 18 @Override 19 protected void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 setContentView(R.layout.main); 22 Button btn = (Button) findViewById(R.id.btn); 23 btn.setOnClickListener(new View.OnClickListener() { 24 @Override 25 public void onClick(View v) { 26 execute(); 27 } 28 }); 29 30 } 31 32 private void execute() { 33 try { 34 MyApplication app = (MyApplication) this.getApplication(); //获取MyApplication实例 35 HttpClient client = app.getHttpClient(); //获取HttpClient实例 36 HttpGet get = new HttpGet("http://192.168.1.57:8080/web/TestServlet?id=1001&name=john&age=60"); 37 HttpResponse response = client.execute(get); 38 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 39 InputStream is = response.getEntity().getContent(); 40 String result = inStream2String(is); 41 Toast.makeText(this, result, Toast.LENGTH_LONG).show(); 42 } 43 } catch (Exception e) { 44 e.printStackTrace(); 45 } 46 } 47 48 //将输入流转换成字符串 49 private String inStream2String(InputStream is) throws Exception { 50 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 51 byte[] buf = new byte[1024]; 52 int len = -1; 53 while ((len = is.read(buf)) != -1) { 54 baos.write(buf, 0, len); 55 } 56 return new String(baos.toByteArray()); 57 } 58 }
在实际应用中,我们不能每次都新建 HttpClient,而是应该只为整个应用创建一个HttpClient,并将其用于所有 HTTP 通信。此外,还应该注意在通过一个 HttpClient 同时发出多个请求时可能发生的多线程问题。针对这两个问题,我们需要改进一下我们的项目:
1、扩展系统默认的 Application,并应用在项目中。
2、使用 HttpClient 类库提供的 ThreadSafeClientManager 来创建和管理 HttpClient。
1 package com.scott.http; 2 3 import org.apache.http.HttpVersion; 4 import org.apache.http.client.HttpClient; 5 import org.apache.http.conn.ClientConnectionManager; 6 import org.apache.http.conn.scheme.PlainSocketFactory; 7 import org.apache.http.conn.scheme.Scheme; 8 import org.apache.http.conn.scheme.SchemeRegistry; 9 import org.apache.http.conn.ssl.SSLSocketFactory; 10 import org.apache.http.impl.client.DefaultHttpClient; 11 import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; 12 import org.apache.http.params.BasicHttpParams; 13 import org.apache.http.params.HttpParams; 14 import org.apache.http.params.HttpProtocolParams; 15 import org.apache.http.protocol.HTTP; 16 17 import android.app.Application; 18 19 public class MyApplication extends Application { 20 21 private HttpClient httpClient; 22 23 @Override 24 public void onCreate() { 25 super.onCreate(); 26 httpClient = this.createHttpClient(); 27 } 28 29 @Override 30 public void onLowMemory() { 31 super.onLowMemory(); 32 this.shutdownHttpClient(); 33 } 34 35 @Override 36 public void onTerminate() { 37 super.onTerminate(); 38 this.shutdownHttpClient(); 39 } 40 41 //创建HttpClient实例 42 private HttpClient createHttpClient() { 43 HttpParams params = new BasicHttpParams(); 44 HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 45 HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET); 46 HttpProtocolParams.setUseExpectContinue(params, true); 47 48 SchemeRegistry schReg = new SchemeRegistry(); 49 schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 50 schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); 51 52 ClientConnectionManager connMgr = new ThreadSafeClientConnManager(params, schReg); 53 54 return new DefaultHttpClient(connMgr, params); 55 } 56 57 //关闭连接管理器并释放资源 58 private void shutdownHttpClient() { 59 if (httpClient != null && httpClient.getConnectionManager() != null) { 60 httpClient.getConnectionManager().shutdown(); 61 } 62 } 63 64 //对外提供HttpClient实例 65 public HttpClient getHttpClient() { 66 return httpClient; 67 } 68 }
在 testUpload 测试用例,我们用 HttpMime 提供的 InputStreamBody 处理文件流参数,用 StringBody 处理普通文本参数,最后把所有类型参数都加入到一个 MultipartEntity 的实例中,并将这个 multipartEntity 设置为此次 POST 请求的参数实体,然后执行 POST请求。
1 package com.scot.http.test; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.InputStream; 5 import java.util.ArrayList; 6 import java.util.List; 7 8 import junit.framework.Assert; 9 10 import org.apache.http.HttpEntity; 11 import org.apache.http.HttpResponse; 12 import org.apache.http.HttpStatus; 13 import org.apache.http.NameValuePair; 14 import org.apache.http.client.HttpClient; 15 import org.apache.http.client.entity.UrlEncodedFormEntity; 16 import org.apache.http.client.methods.HttpGet; 17 import org.apache.http.client.methods.HttpPost; 18 import org.apache.http.entity.mime.MultipartEntity; 19 import org.apache.http.entity.mime.content.InputStreamBody; 20 import org.apache.http.entity.mime.content.StringBody; 21 import org.apache.http.impl.client.DefaultHttpClient; 22 import org.apache.http.message.BasicNameValuePair; 23 24 import android.test.AndroidTestCase; 25 26 public class HttpTest extends AndroidTestCase { 27 28 private static final String PATH = "http://192.168.1.57:8080/web"; 29 30 public void testGet() throws Exception { 31 HttpClient client = new DefaultHttpClient(); 32 HttpGet get = new HttpGet(PATH + "/TestServlet?id=1001&name=john&age=60"); 33 HttpResponse response = client.execute(get); 34 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 35 InputStream is = response.getEntity().getContent(); 36 String result = inStream2String(is); 37 Assert.assertEquals(result, "GET_SUCCESS"); 38 } 39 } 40 41 public void testPost() throws Exception { 42 HttpClient client = new DefaultHttpClient(); 43 HttpPost post = new HttpPost(PATH + "/TestServlet"); 44 List<NameValuePair> params = new ArrayList<NameValuePair>(); 45 params.add(new BasicNameValuePair("id", "1001")); 46 params.add(new BasicNameValuePair("name", "john")); 47 params.add(new BasicNameValuePair("age", "60")); 48 HttpEntity formEntity = new UrlEncodedFormEntity(params); 49 post.setEntity(formEntity); 50 HttpResponse response = client.execute(post); 51 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 52 InputStream is = response.getEntity().getContent(); 53 String result = inStream2String(is); 54 Assert.assertEquals(result, "POST_SUCCESS"); 55 } 56 } 57 58 public void testUpload() throws Exception { 59 InputStream is = getContext().getAssets().open("books.xml"); 60 HttpClient client = new DefaultHttpClient(); 61 HttpPost post = new HttpPost(PATH + "/UploadServlet"); 62 InputStreamBody isb = new InputStreamBody(is, "books.xml"); 63 MultipartEntity multipartEntity = new MultipartEntity(); 64 multipartEntity.addPart("file", isb); 65 multipartEntity.addPart("desc", new StringBody("this is description.")); 66 post.setEntity(multipartEntity); 67 HttpResponse response = client.execute(post); 68 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 69 is = response.getEntity().getContent(); 70 String result = inStream2String(is); 71 Assert.assertEquals(result, "UPLOAD_SUCCESS"); 72 } 73 } 74 75 //将输入流转换成字符串 76 private String inStream2String(InputStream is) throws Exception { 77 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 78 byte[] buf = new byte[1024]; 79 int len = -1; 80 while ((len = is.read(buf)) != -1) { 81 baos.write(buf, 0, len); 82 } 83 return new String(baos.toByteArray()); 84 } 85 }
服务端 Servlet 使用 apache 开源项目 FileUpload 进行处理,所以需要 commons-fileupload 和 commons-io 这两个项目的 jar 包。
1 package com.scott.web.servlet; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.util.Iterator; 6 import java.util.List; 7 8 import javax.servlet.ServletException; 9 import javax.servlet.http.HttpServlet; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 13 import org.apache.commons.fileupload.FileItem; 14 import org.apache.commons.fileupload.FileItemFactory; 15 import org.apache.commons.fileupload.FileUploadException; 16 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 17 import org.apache.commons.fileupload.servlet.ServletFileUpload; 18 19 @SuppressWarnings("serial") 20 public class UploadServlet extends HttpServlet { 21 22 @Override 23 @SuppressWarnings("rawtypes") 24 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 25 boolean isMultipart = ServletFileUpload.isMultipartContent(request); 26 if (isMultipart) { 27 FileItemFactory factory = new DiskFileItemFactory(); 28 ServletFileUpload upload = new ServletFileUpload(factory); 29 try { 30 List items = upload.parseRequest(request); 31 Iterator iter = items.iterator(); 32 while (iter.hasNext()) { 33 FileItem item = (FileItem) iter.next(); 34 if (item.isFormField()) { 35 //普通文本信息处理 36 String paramName = item.getFieldName(); 37 String paramValue = item.getString(); 38 System.out.println(paramName + ":" + paramValue); 39 } else { 40 //上传文件信息处理 41 String fileName = item.getName(); 42 byte[] data = item.get(); 43 String filePath = getServletContext().getRealPath("/files") + "/" + fileName; 44 FileOutputStream fos = new FileOutputStream(filePath); 45 fos.write(data); 46 fos.close(); 47 } 48 } 49 } catch (FileUploadException e) { 50 e.printStackTrace(); 51 } 52 } 53 response.getWriter().write("UPLOAD_SUCCESS"); 54 } 55 }
HttpMime 处理 多部件 POST 请求的更多相关文章
- Android中使用HTTP服务
在Android中,除了使用java.net包下的API访问HTTP服务之外,我们还可以换一种途径去完成工作.Android SDK附带了Apache的HttpClient API.Apache Ht ...
- HttpClient 4.5.x 工具类设计与实现
最近,业务需要在java服务端发起http请求,需要实现"GET","POST","PUT"等基本方法.于是想以 "HttpCli ...
- Composite模式
1 意图:将对象组成树形结构,以表示“部分——整体”的层次结构.Composite使得用户对单个对象和组合对象的使用具有一致性. 2 动机:同意处理图元对象和包含图元的容器对象.Composite通过 ...
- ASP.NET Core重写个人博客站点小结
今天用ASP.NET Core重写了个人博客站点,原来是基于ASP.NET 4.5开发的.重写工作总体很顺利,最后成功发布到Ubunt+Nginx平台上.效果如下: 右边的Header信息里可以看到已 ...
- MEF 编程指南(十二):批量组合
MEF 容器实例并非不可变的.如果目录支持改变(像监控目录变动)或者在运行时添加/移除部件都可能发生改变.以前,你不得不做出改动并且调用 CompositionContainer 上的 Compose ...
- NET Core个人博客
NET Core重写个人博客站点小结 今天用ASP.NET Core重写了个人博客站点,原来是基于ASP.NET 4.5开发的.重写工作总体很顺利,最后成功发布到Ubunt+Nginx平台上.效果如下 ...
- Java解析导入Excel文件后台代码实现
使用MultipartFile上传Excel文件后端代码实现:(springmvc下的spring-webmvc (MultipartFile )上传) 由于POST一个包含文件上传的Form会以mu ...
- Odoo Javascript 参考
本文介绍了odoo javascript框架.从代码行的角度来看,这个框架不是一个大的应用程序,但它是非常通用的,因为它基本上是一个将声明性接口描述转换为活动应用程序的机器,能够与数据库中的每个模型和 ...
- Sentry(v20.12.1) K8S 云原生架构探索,JavaScript Enriching Events(丰富事件信息)
系列 Sentry-Go SDK 中文实践指南 一起来刷 Sentry For Go 官方文档之 Enriching Events Snuba:Sentry 新的搜索基础设施(基于 ClickHous ...
随机推荐
- ABAP 向上取整和向下取整 CEIL & FLOOR
下面是一段关于CEIL 和 FLOOR 的代码 DATA:a TYPE mseg-menge, b TYPE mseg-menge, c TYPE mseg-menge. a = '1.36'. b ...
- 进阶:案例五: Dynamic 创建 Business Graphic
效果图: step: 无需节点无需UI 1.添加属性 2.代码: method WDDOMODIFYVIEW . DATA:lr_graph TYPE REF TO cl_wd_business_gr ...
- org.springframework.core.Ordered接口
关于Ordered接口,用过的人可能知道,这里我谈下自己的理解.也希望各位大神能给予指点. 源码如下: /** * Interface that can be implemented by obje ...
- [知识库分享系列] 二、Web(高性能Web站点建设)
知识库分享系列: [知识库分享系列] 二..NET(ASP.NET) [知识库分享系列] 一.开篇 分享介绍 此知识库之所以为 Web 系列,因为和 .NET 没有完全的关系,其中的技术和实践实用于各 ...
- RobotFrameWork(十一)AutoItLibrary测试库在win7(64bit)下安装及简单使用
最近安装AutoItLibrary,发现在win7 x64下无法安装成功,后来经过定位,发现是3rdPartyTools\AutoIt目录下面AutoItX3.dll的问题.因为AutoItX3.dl ...
- android百度地图打包混淆 用不了No such file or directory (2) com.baidu.mapapi.BMapManager.init(Unknown Source)
调用了百度地图地图开发包是baidumapapi_v2_1_1.jar,定位SDK版本是locSDK_3.3.jar 调试的时候能运行!可是打包签名后就运行不了! baidu google 了好久! ...
- WM_PAINT产生原因有2种(用户操作和API)——WM_PAINT和WM_ERASEBKGND产生时的先后顺序不一定(四段讨论)
1. 当WM_PAINT不是由InvalidateRect产生时,即由最大化,最小化等产生时,或者移动产生(移动有时只会产生WM_ERASEBKGND消息)系统先发送WM_ERASEBKGND消息,再 ...
- 调整Tomcat的并发线程到5000+
调整Tomcat的并发线程数到5000+ 1. 调整server.xml的配置 先调整maxThreads的数值,在未调整任何参数之前,默认的并发线程可以达到40. 调整此项后可以达到1800左右. ...
- web框架python
22.python笔记之web框架 一.web框架本质 1.基于socket,自己处理请求 #!/usr/bin/env python3 #coding:utf8 import socket de ...
- Struts2 后台action接收 jsp页面中checkbox中的值
如前端页面jsp中的标签为: <form action="myurl"> <input type="checkbox" name=" ...