yyyyyyyyyyyyyyyyyyyy

博客园 首页 新随笔 联系 订阅 管理

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 }
复制代码
posted on 2015-10-13 15:46  xxxxxxxx1x2xxxxxxx  阅读(322)  评论(0)    收藏  举报