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

Spring Boot结合aws-serverless-java-container的Multipart表单上传异常

解决API Gateway + Spring Boot Lambda处理Multipart文件上传的415错误

问题背景

实现了一个Multipart POST接口,接收userId和Multipart文件作为输入,将文件保存到S3存储桶中以userId命名的文件夹内。本地运行Spring Boot应用时功能正常,但通过API Gateway调用端点时,出现415 UNSUPPORTED_MEDIA_TYPE错误,提示Content type 'application/octet-stream' not supported for bodyType=org.springframework.web.multipart.MultipartFile。

控制器代码

@RestController
@RequestMapping("/api/v1/forms")
public class FormController {
    private static final Logger log = LoggerFactory.getLogger(FormController.class);
    @Autowired
    private S3Service s3Service;
    @Value("${application.awsClient.legalFormsBucket}")
    String legalFormBucket;

    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<String> uploadFile(@RequestPart("userId") String userId,
            @RequestPart("file") MultipartFile file, HttpServletRequest request) {

        log.info("Request Content-Type: {}", request.getContentType());
        try {
            s3Service.uploadFile(userId, file);
            return ResponseEntity.badRequest().body("");
        } catch (IOException e) {
            return ResponseEntity.status(500).body("File upload failed: " + e.getMessage());
        }
    }
}

Lambda处理器代码

public class StreamLambdaHandler implements RequestStreamHandler {
    private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
    static {
        try {
            handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(TaxtranscriptproApplication.class);
            handler.getServletContext().setInitParameter("binaryContentTypes",
                    "multipart/form-data,application/octet-stream,application/pdf,image/png,image/jpeg");
        } catch (ContainerInitializationException e) {
            e.printStackTrace();
            throw new RuntimeException("Could not initialize Spring Boot application", e);
        }
    }

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
            throws IOException {

        handler.proxyStream(inputStream, outputStream, context);
    }
}

错误日志

Decoding part 'userId'
No Content-Type, using application/octet-stream

[java.lang.String]
Decoded "92a5c4c4-8051-703c-11db-e1babe222de4"
Decoding part 'file'
Content-Type:application/octet-stream Could not resolve parameter [1] in public org.springframework.http.ResponseEntity<java.lang.String> com.example.taxtranscriptpro.controller.FormController.uploadFile(java.lang.String,org.springframework.web.multipart.MultipartFile,jakarta.servlet.http.HttpServletRequest): 415 UNSUPPORTED_MEDIA_TYPE "Content type 'application/octet-stream' not supported for bodyType=org.springframework.web.multipart.MultipartFile"

解决方案

1. 修正API Gateway二进制媒体类型配置

  • 确保API Gateway的二进制媒体类型中添加multipart/form-data,并且使用**通配符multipart/***覆盖所有multipart子类型(避免因请求带边界参数导致匹配失败)。
  • 在API Gateway的集成请求设置中,将内容处理改为Convert to binary (if needed),确保原始multipart二进制数据不被转成文本格式转发。

2. 调整Lambda处理器的二进制内容配置

修改Lambda初始化代码,确保Spring容器能正确识别并解码multipart请求:

static {
    try {
        handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(TaxtranscriptproApplication.class);
        // 扩展二进制类型覆盖范围,确保multipart请求能被正确解码
        handler.getServletContext().setInitParameter("binaryContentTypes",
                "multipart/*,application/octet-stream,application/pdf,image/png,image/jpeg");
    } catch (ContainerInitializationException e) {
        e.printStackTrace();
        throw new RuntimeException("Could not initialize Spring Boot application", e);
    }
}

3. 显式配置Spring Multipart解析器

添加配置类确保Lambda环境下Multipart解析正常工作:

@Configuration
public class MultipartConfig {
    @Bean
    public MultipartResolver multipartResolver() {
        StandardServletMultipartResolver resolver = new StandardServletMultipartResolver();
        return resolver;
    }

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        // 设置最大上传文件大小,根据业务需求调整
        factory.setMaxFileSize(DataSize.ofMegabytes(50));
        factory.setMaxRequestSize(DataSize.ofMegabytes(50));
        return factory.createMultipartConfig();
    }
}

4. 优化控制器参数注解

确保文件参数的注解明确指定需求,同时验证请求发送时文件部分的Content-Type是否正确(如PDF对应application/pdf):

@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> uploadFile(
        @RequestPart("userId") String userId,
        @RequestPart(value = "file", required = true) MultipartFile file, 
        HttpServletRequest request) {
    // 业务逻辑保持不变
}

错误原因分析

API Gateway转发请求时,将文件部分的Content-Type强制改为application/octet-stream,导致Spring的Multipart解析器无法将该类型映射到MultipartFile接口。本质是API Gateway二进制类型配置不完整,或Lambda处理器未正确解码multipart请求结构导致的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:25:02