Contents

Apache Httpclient分段上传

1. 概述

在本教程中,我们将说明如何使用 HttpClient 进行分段上传操作

我们将使用http://echo.200please.com 作为测试服务器,因为它是公开的并且可以接受大多数类型的内容。

2. 使用AddPart方法

让我们从查看MultipartEntityBuilder对象开始,将部分添加到 Http 实体,然后通过 POST 操作上传。

这是一种将部件添加到表示表单的HttpEntity的通用方法。

2.1. 上传包含两个文本部分和一个文件的表单

File file = new File(textFileName);
HttpPost post = new HttpPost("http://echo.200please.com");
FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY);
StringBody stringBody1 = new StringBody("Message 1", ContentType.MULTIPART_FORM_DATA);
StringBody stringBody2 = new StringBody("Message 2", ContentType.MULTIPART_FORM_DATA);
// 
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addPart("upfile", fileBody);
builder.addPart("text1", stringBody1);
builder.addPart("text2", stringBody2);
HttpEntity entity = builder.build();
//
post.setEntity(entity);
HttpResponse response = client.execute(post);

请注意,我们还通过指定要由服务器使用的ContentType值来实例化File对象。

另外,请注意addPart方法有两个参数,作用类似于表单的key/value对。仅当服务器端实际期望并使用参数名称时,这些才是相关的——否则,它们会被简单地忽略。

3. 使用addBinaryBodyaddTextBody方法

创建多部分实体的更直接方法是使用addBinaryBodyAddTextBody方法。这些方法适用于上传文本、文件、字符数组和InputStream对象。让我们用简单的例子来说明如何。

3.1. 上传文本和文本文件部分

HttpPost post = new HttpPost("http://echo.200please.com");
File file = new File(textFileName);
String message = "This is a multipart post";
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("upfile", file, ContentType.DEFAULT_BINARY, textFileName);
builder.addTextBody("text", message, ContentType.DEFAULT_BINARY);
// 
HttpEntity entity = builder.build();
post.setEntity(entity);
HttpResponse response = client.execute(post);

请注意,此处不需要FileBodyStringBody对象。

同样重要的是,大多数服务器不会检查文本正文的ContentType,因此addTextBody方法可能会省略ContentType值。

addBinaryBody API 接受ContentType - 但也可以仅从二进制正文和保存文件的表单参数的名称创建实体。如上一节所述,如果未指定ContentType值,某些服务器将无法识别该文件。

接下来,我们将添加一个 zip 文件作为InputStream,而图像文件将添加为File对象:

3.2. 上传Zip 文件、图像文件和文本部分

HttpPost post = new HttpPost("http://echo.200please.com");
InputStream inputStream = new FileInputStream(zipFileName);
File file = new File(imageFileName);
String message = "This is a multipart post";
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody
  ("upfile", file, ContentType.DEFAULT_BINARY, imageFileName);
builder.addBinaryBody
  ("upstream", inputStream, ContentType.create("application/zip"), zipFileName);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
// 
HttpEntity entity = builder.build();
post.setEntity(entity);
HttpResponse response = client.execute(post);

请注意,可以动态创建ContentType值,就像上面的 zip 文件示例中的情况一样。

最后,并非所有服务器都承认InputStream部分。我们在第一行代码中实例化的服务器识别InputStream

现在让我们看一下addBinaryBody直接使用字节数组的另一个示例:

3.3. 上传字节数组和文本

HttpPost post = new HttpPost("http://echo.200please.com");
String message = "This is a multipart post";
byte[] bytes = "binary code".getBytes(); 
// 
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("upfile", bytes, ContentType.DEFAULT_BINARY, textFileName);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
// 
HttpEntity entity = builder.build();
post.setEntity(entity);
HttpResponse response = client.execute(post);

注意ContentType - 现在指定二进制数据。