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

网关微服务转发Multipart文件失败 下游接收file参数为null

问题根因
  • 网关转发时构造的请求不符合multipart/form-data文件上传协议规范,下游Spring MVC无法解析出名为file的MultipartFile参数,最终拿到null。
  • 原有实现直接将文件字节数组塞入HttpEntity发送,默认请求头Content-Type为application/octet-stream,既没有指定表单字段名,也没有multipart请求要求的boundary分隔符、文件元数据(文件名等),完全不符合文件上传接口的请求格式要求。
  • 直连下游服务正常,是因为调用方直接发送了标准multipart格式请求,Spring可以正常解析参数。
修复方案

替换网关层try代码块内的请求构造逻辑,构造标准的multipart表单请求转发即可,代码如下:

try {
    // 构造multipart表单请求体
    MultiValueMap<String, Object> formBody = new LinkedMultiValueMap<>();
    
    // 将文件包装为字节数组资源,指定表单字段名与下游接口参数名一致为file
    formBody.add("file", new ByteArrayResource(file.getBytes()){
        // 必须重写getFilename返回文件名,否则下游无法识别为文件字段
        @Override
        public String getFilename() {
            return file.getOriginalFilename();
        }
    });

    // 构造请求头,指定Content-Type为multipart/form-data
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.MULTIPART_FORM_DATA);

    // 组装请求实体并转发
    HttpEntity<MultiValueMap<String, Object>> forwardRequest = new HttpEntity<>(formBody, headers);
    ResponseEntity<DocumentResponseDTO> entity = restTemplate.postForEntity(uriStatementUpload.toUri(), forwardRequest, DocumentResponseDTO.class);
    return entity;
} catch (HttpClientErrorException e) {
    return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsString());
} catch (IOException e) {
    return ResponseEntity.status(500).body("IOException while getting bytes stream from file");
}
注意事项
  • 不要直接传入裸byte数组作为请求体,必须使用LinkedMultiValueMap作为multipart表单的载体,这是Spring RestTemplate处理文件上传的标准数据结构
  • 包装文件资源时必须重写getFilename()方法返回原始文件名,否则Spring构造请求时不会为该字段生成filename属性,下游依然会解析失败
  • 表单字段的key必须为file,和下游接口的形参名完全匹配,否则参数绑定会失败
  • 不需要手动设置multipart请求的boundary参数,RestTemplate会在发送请求时自动生成合法的分隔符

内容的提问来源于stack exchange,提问作者Eljah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:39:20