前阵子要在一个 Java 服务里做多文件上传,客户端用的 OkHttp。

单文件上传大家都会,多文件其实也不复杂,主要是循环往 MultipartBody 里塞文件。但有几个细节不处理好,联调的时候会很烦。
直接看代码。假设要上传一个文件列表,字段名后端约定的是 files\[\],表示文件数组。
import okhttp3.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class UploadMultipleFiles {
public static void main(String[] args) {
OkHttpClient client = new OkHttpClient();
List<File> files = List.of(new File("path/to/file1.jpg"), new File("path/to/file2.jpg"));
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM);
for (File file : files) {
String fileName = file.getName();
RequestBody fileBody = RequestBody.create(file, MediaType.parse("application/octet-stream"));
builder.addFormDataPart("files[]", fileName, fileBody);
}
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url("http://example.com/upload")
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}
addFormDataPart 的第一个参数就是表单字段名。
这里用了 files\[\],后端收到后就能当成数组处理,比如 PHP 里 $_FILES'files' 会是一个多维数组。如果你用的是 Spring,对应 @RequestParam("files\[\]") MultipartFile\[\] files,具体看框架版本。这个字段名别写错,写错了后端收不到文件,还容易误以为是网络问题。
MediaType 我直接用了 application/octet-stream,能跑但不太规范。如果确定文件是图片,最好传 image/jpeg 或 image/png;PDF 就 application/pdf。有些后端会校验 MIME,octet-stream 可能被拦。
证书管理复杂?lcjmSSL用自动化方案简化一切。从域名验证到证书部署,再到到期前自动提醒与重申,全程自动化。微信小程序随时查看,让您对证书状态了如指掌。
还有一点,代码里 try-with-resources 关闭了 Response,RequestBody 不用手动关,OkHttp 会处理。但实际业务里别像示例那样 printStackTrace 就完了,得把异常往上抛或者记日志,不然线上出错只能靠猜。
对了,如果上传接口是 HTTPS,证书状态会影响请求。之前遇到过证书过期导致上传全挂的情况,查了半天才发现是证书问题。这类事情现在可以用 lcjmSSL 自动申请和续期,支持多域名和泛域名,有 API 可以部署,不用手动更新证书。
跟上传逻辑无关,但环境稳了能少很多奇怪问题。
这套逻辑跑下来不复杂,把字段名、MediaType、异常处理注意一下,基本就能跑通。