You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Java HttpURLConnection发送二进制内容到SpringBoot服务报错如何解决

问题原因

  • 服务端配置冲突:接口要求请求Content-Type为multipart/form-data,但使用@RequestBody注解默认只能处理application/json等非multipart类型的请求体,Spring找不到对应转换器解析请求。
  • 客户端请求格式错误:虽然设置了multipart/form-data的请求头,但实际发送的是普通JSON字符串,且没有携带multipart协议要求的边界(boundary)分隔符,服务端无法识别请求格式,默认将请求识别为text/plain;charset=UTF-8,和接口要求的类型不匹配,因此抛出异常。
  • 字节数组传输逻辑错误:使用Arrays.toString(bytes)将二进制数组转为字符串格式存入JSON,会导致二进制内容失真,体积膨胀,无法正确还原原始文件内容。

修复方案

根据业务场景可以选择以下两种方案之一:

方案1:走multipart/form-data协议传输二进制(推荐用于文件上传,效率更高)

服务端修改

// 移除硬编码的content-type要求,改用consumes声明,接收参数换成MultipartFile
@RequestMapping(value = "/bytelink", method = RequestMethod.POST, consumes = "multipart/form-data")
ResponseEntity<String> postBytes(@ApiParam(value = "Upload bytes") @RequestParam("file") MultipartFile file) throws IOException {                   
    return ResponseEntity.ok(byteLinkService.postBytes(file.getBytes()));
}

客户端修改

//byte[] bytes 是待上传的文件内容
String boundary = "----Boundary" + Long.toHexString(System.currentTimeMillis());
URL url = new URL(this.endpoint + "/bytelink/");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Authorization", "Bearer " + token);
// 请求头携带边界参数
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
con.setRequestProperty("Accept", "*/*");
con.setDoOutput(true);

try (OutputStream os = con.getOutputStream()) {
    // 写入multipart起始分隔符
    os.write(("--" + boundary + "\r\n").getBytes());
    // 写入文件字段头信息
    os.write(("Content-Disposition: form-data; name=\"file\"; filename=\"upload.bin\"\r\n").getBytes());
    os.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes());
    // 直接写入原始二进制内容
    os.write(bytes);
    // 写入multipart结束分隔符
    os.write(("\r\n--" + boundary + "--\r\n").getBytes());
    os.flush();
}

int status = con.getResponseCode();
System.out.println(status);

方案2:走application/json协议传输(适合小体积字节数组)

服务端修改

// 把接收类型改成application/json,保留@RequestBody接收自定义Bytes对象即可
@RequestMapping(value = "/bytelink", method = RequestMethod.POST, consumes = "application/json")
ResponseEntity<String> postBytes(@ApiParam(value = "Upload bytes.", example = "0") @RequestBody Bytes bytes) {                   
    return ResponseEntity.ok(byteLinkService.postBytes(bytes.getBytes()));
}

客户端修改

import java.util.Base64;
import java.nio.charset.StandardCharsets;

//byte[] bytes 是待上传的文件内容
URL url = new URL(this.endpoint + "/bytelink/");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Authorization", "Bearer " + token);
// 改成json格式请求头
con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
con.setRequestProperty("Accept", "*/*");
con.setDoOutput(true);

// 字节数组转Base64编码,避免二进制内容在JSON中转义出错
String base64Bytes = Base64.getEncoder().encodeToString(bytes);
String jsonInputString = "{\"bytes\": \"" + base64Bytes + "\"}";
try (OutputStream os = con.getOutputStream()) {
    byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
    os.write(input, 0, input.length);           
}

int status = con.getResponseCode();
System.out.println(status);

内容的提问来源于stack exchange,提问作者k-wasilewski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 19:57:03