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方法
更直接的方式是使用addBinaryBody
和addTextBody
方法。这些方法支持上传文本、文件、字符数组和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 -> {
// 处理响应
});
}
✅ 关键点:
- 此处无需创建
FileBody
和StringBody
对象 - 多数服务器不检查文本体的
ContentType
,addTextBody
可省略该参数 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
方法:更直接,支持文件/文本/流/字节数组 - ⚠️ 服务器兼容性:部分服务器对
ContentType
和InputStream
支持有限
所有示例代码可在GitHub项目中获取,直接导入即可运行。