Spring WebFlux接收FilePart后如何在存盘前将其转换为File?
实现方案
核心逻辑
org.springframework.http.codec.multipart.FilePart是反应式流的封装,本身不会直接持有全量的文件数据,所以你可以先把数据流写入本地临时文件,完成大小、分辨率校验通过后再移动到正式存储目录,校验失败直接删除临时文件即可。
完整代码实现
import java.nio.file.Files import java.nio.file.StandardCopyOption import javax.imageio.ImageIO import kotlin.jvm.Throws @PostMapping("file/single") fun upload1(@RequestPart("image") image: FilePart): Mono<Void> { // 可自定义配置的最大文件大小 示例为5MB val maxAllowedSize = 5 * 1024 * 1024L // 可自定义配置的最小图片分辨率 val requiredMinWidth = 200 val requiredMinHeight = 200 return Mono.using( // 第一步:创建临时文件存储上传内容 { Files.createTempFile("upload_tmp_", image.filename()) }, { tempFilePath -> // 把FilePart内容写入临时文件 image.transferTo(tempFilePath) .then(Mono.fromCallable { val tempFile = tempFilePath.toFile() // 校验文件大小 if (tempFile.length() > maxAllowedSize) { throw IllegalArgumentException("文件大小超出5MB上限") } // 转换为BufferedImage校验分辨率 val bufferedImage = ImageIO.read(tempFile) ?: throw IllegalArgumentException("上传文件不是合法的图片格式") if (bufferedImage.width < requiredMinWidth || bufferedImage.height < requiredMinHeight) { throw IllegalArgumentException("图片分辨率不能小于${requiredMinWidth}*${requiredMinHeight}") } // 所有校验通过,将临时文件移动到正式存储目录 val targetPath = paths.STORAGE_PATH.resolve(image.filename()) Files.move(tempFilePath, targetPath, StandardCopyOption.REPLACE_EXISTING) }) .then() }, // 无论校验成功失败都自动清理临时文件,不会产生冗余垃圾文件 { tempFilePath -> Files.deleteIfExists(tempFilePath) } ) }
注意事项
- 如果你需要支持webp等非常规图片格式,可自行扩展ImageIO的格式支持插件即可
- 上述代码基于Spring 5.1+版本验证可用,低版本Spring需要确认FilePart的transferTo方法支持Path类型参数
内容的提问来源于stack exchange,提问作者Vova backend_dev
相关产品推荐
相关产品推荐

