1. 概述

本教程将演示如何使用Apache HttpClient 5实现多部分上传操作

如果你想深入探索HttpClient的更多高级用法,可以参考HttpClient核心教程

2. 使用addPart方法

我们先通过MultipartEntityBuilder对象向Http实体添加多部分内容,然后通过POST请求上传。

这是构建表单式Http实体的通用方法。

示例2.1 – 上传包含两个文本字段和一个文件的表单

final File file = new File(url.getPath());
final FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY);
final StringBody stringBody1 = new StringBody("This is message 1", ContentType.MULTIPART_FORM_DATA);
final StringBody stringBody2 = new StringBody("This is message 2", ContentType.MULTIPART_FORM_DATA);

final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.LEGACY);
builder.addPart("file", fileBody);
builder.addPart("text1", stringBody1);
builder.addPart("text2", stringBody2);
final HttpEntity entity = builder.build();

post.setEntity(entity);
try(CloseableHttpClient client = HttpClientBuilder.create()
    .build()) {

    client.execute(post, response -> { 
       // 处理响应
    });
}

⚠️ 注意:

  • 创建File对象时需指定服务器期望的ContentType
  • addPart方法的两个参数相当于表单的键值对
  • 仅当服务器端实际需要并使用参数名时,这些键值对才有效

3. 使用addBinaryBody和addTextBody方法

更直接的方式是使用addBinaryBodyaddTextBody方法。这些方法支持上传文本、文件、字符数组和InputStream对象。下面通过示例说明:

示例3.1 – 上传文本和文本文件

final File file = new File(url.getPath());
final String message = "This is a multipart post";
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.LEGACY);
builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, TEXTFILENAME);
builder.addTextBody("text", message, ContentType.DEFAULT_BINARY);
final HttpEntity entity = builder.build();
post.setEntity(entity);

try(CloseableHttpClient client = HttpClientBuilder.create()
    .build()) {

    client.execute(post, response -> { 
       // 处理响应
    });
}

✅ 关键点:

  • 此处无需创建FileBodyStringBody对象
  • 多数服务器不检查文本体的ContentTypeaddTextBody可省略该参数
  • addBinaryBody接受ContentType参数,但也可仅通过二进制体和文件名创建实体(部分服务器需要指定ContentType才能识别文件)

示例3.2 – 上传ZIP文件、图片文件和文本

final URL url = Thread.currentThread()
  .getContextClassLoader()
  .getResource("uploads/" + ZIPFILENAME);
final URL url2 = Thread.currentThread()
  .getContextClassLoader()
  .getResource("uploads/" + IMAGEFILENAME);
final InputStream inputStream = new FileInputStream(url.getPath());
final File file = new File(url2.getPath());
final String message = "This is a multipart post";
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.LEGACY);
builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, IMAGEFILENAME);
builder.addBinaryBody("upstream", inputStream, ContentType.create("application/zip"), ZIPFILENAME);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
final HttpEntity entity = builder.build();
post.setEntity(entity);

try(CloseableHttpClient client = HttpClientBuilder.create()
    .build()) {

    client.execute(post, response -> { 
       // 处理响应
    });
}

⚠️ 注意:

  • ContentType可动态创建(如ZIP文件的示例)
  • 并非所有服务器都支持InputStream类型上传(示例中的服务器支持)

示例3.3 – 上传字节数组和文本

final String message = "This is a multipart post";
final byte[] bytes = "binary code".getBytes();
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.LEGACY);
builder.addBinaryBody("file", bytes, ContentType.DEFAULT_BINARY, TEXTFILENAME);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
final HttpEntity entity = builder.build();
post.setEntity(entity);

try(CloseableHttpClient client = HttpClientBuilder.create()
    .build()) {

    client.execute(post, response -> { 
       // 处理响应
    });
}

✅ 关键点:

  • ContentType明确指定为二进制数据
  • 直接操作字节数组的方式简单粗暴,适合小文件上传

4. 总结

本文展示了MultipartEntityBuilder作为灵活工具,提供多种API创建多部分表单:

  • addPart方法:通用性强,适合复杂表单结构
  • addBinaryBody/addTextBody方法:更直接,支持文件/文本/流/字节数组
  • ⚠️ 服务器兼容性:部分服务器对ContentTypeInputStream支持有限

所有示例代码可在GitHub项目中获取,直接导入即可运行。


原始标题:Multipart Upload with Apache HttpClient

« 上一篇: Baeldung Weekly 20
» 下一篇: Java周报 21