zoukankan      html  css  js  c++  java
  • 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 }
    复制代码
  • 相关阅读:
    mysql 中文字段排序( UTF8按拼音首字母排序)
    输入输出挂
    HDU 6301 贪心
    HDU1533 最小费用最大流
    POJ 2135 最小费用最大流 入门题
    HDU 6278 主席树(区间第k大)+二分
    HDU3549 最大流 裸题
    2018牛客网暑期ACM多校训练营(第一场)D图同构,J
    POJ 1804 逆序对数量 / 归并排序
    Codeforces Round #489 (Div. 2) B、C
  • 原文地址:https://www.cnblogs.com/timssd/p/4874834.html
Copyright © 2011-2022 走看看