使用MultipartFormEntity发送File与byte[]的差异及问题排查
当你使用addBinaryBody("content", fileBytes)创建multipart实体时,Apache HttpClient默认会将字节数组当作文本类型字段处理,自动对原始字节进行Base64编码后发送。这就导致服务器端@RequestParam("content") byte[]接收到的是Base64编码后的字节数组,而非原始文件字节——Base64编码会让数据体积增加约33%(298254 * 1.33 ≈ 347739),正好和你看到的结果匹配。
而使用addBinaryBody("content", file)时,HttpClient会自动识别这是文件类型,以原始二进制流的形式发送,不会进行编码,因此服务器端的MultipartFile能正确解析出原始字节数。
你尝试添加ContentType.BINARY_FILE和filename.bin参数后,HttpClient会将该字段当作文件部件发送,这时候服务器的MultipartFile接口能正确处理(因为它专门适配multipart文件部件),但@RequestParam("content") byte[]仍然无法正确获取原始字节的原因是:Spring对于@RequestParam接收multipart请求中二进制部件的逻辑,不会自动提取原始二进制内容,而是仍按文本字段的解析逻辑处理。
方案1:让HttpClient发送未编码的原始字节数组
在调用addBinaryBody时,显式指定ContentType.APPLICATION_OCTET_STREAM,强制HttpClient将字节数组作为二进制字段发送,避免Base64编码:
var fileBytes = Files.readAllBytes(Path.of(path)); HttpEntity multipartByteArr = MultipartEntityBuilder.create() .addBinaryBody("content", fileBytes, ContentType.APPLICATION_OCTET_STREAM, null) .build();
这样服务器端的byteArr接口就能接收到和原始文件一致的字节数。
方案2:调整服务器端接口适配multipart请求
如果不需要单独的byteArr接口,直接复用multipart接口即可,在方法内部将MultipartFile转为字节数组:
@PostMapping("multipart") public void multipart(@RequestParam("content") MultipartFile file) throws IOException { byte[] fileBytes = file.getBytes(); System.out.println(fileBytes.length); }
或者将byteArr接口改为使用@RequestPart接收:
@PostMapping("byteArr") public void byteArr(@RequestPart("content") byte[] fileBytes) { System.out.println(fileBytes.length); }
内容的提问来源于stack exchange,提问作者diogoaos

