SpringBoot WebFlux大文件上传异常:仅支持500KB以下文件
问题原因与解决方案
核心原因
- 错误读取分片数据:
attachment.content()返回Flux<DataBuffer>,大文件会被拆分为多个DataBuffer分片传输,awaitFirst()仅获取了第一个分片(默认大小1024字节),导致仅读取部分内容。 - 配置不匹配:WebFlux基于Reactor Netty而非Servlet容器,
spring.servlet.multipart配置对WebFlux无效。
解决方案
1. 正确读取完整文件内容
收集所有DataBuffer分片并合并为完整字节数组,修改控制器代码:
@RestController @RequestMapping("/emailFile") class EmailController { val logger = LoggerFactory.getLogger(this::class.java) @PostMapping("/upload", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE]) suspend fun uploadFile( @RequestPart("attachment") attachment: FilePart, @RequestPart("message") message: String ): ResponseEntity<String> { // 收集所有分片并合并 val dataBuffers = attachment.content().collectList().awaitSingle() val totalSize = dataBuffers.sumOf { it.readableByteCount() } val mergedBuffer = ByteBuffer.allocate(totalSize) dataBuffers.forEach { buffer -> mergedBuffer.put(buffer.asByteBuffer()) buffer.release() // 释放资源避免内存泄漏 } mergedBuffer.flip() logger.debug(mergedBuffer.array().size.toString()) File("testfilespring.png").writeBytes(mergedBuffer.array()) return ResponseEntity(message, HttpStatus.ACCEPTED) } }
2. 配置WebFlux专属的上传限制
替换原Servlet配置,使用WebFlux参数:
spring: codec: max-in-memory-size: 10MB # 内存中允许的最大文件大小,超过则写入临时文件 webflux: multipart: max-file-size: 10MB max-request-size: 10MB
优化方案(推荐)
处理大文件时,直接使用transferTo写入磁盘,无需手动处理字节,自动分片合并和资源释放:
@RestController @RequestMapping("/emailFile") class EmailController { val logger = LoggerFactory.getLogger(this::class.java) @PostMapping("/upload", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE]) suspend fun uploadFile( @RequestPart("attachment") attachment: FilePart, @RequestPart("message") message: String ): ResponseEntity<String> { // 直接写入文件 attachment.transferTo(File("testfilespring.png")).awaitSingle() logger.debug("文件上传完成") return ResponseEntity(message, HttpStatus.ACCEPTED) } }
内容的提问来源于stack exchange,提问作者Michal
相关产品推荐
相关产品推荐

