WebFlux处理FilePart后删除本地文件并返回Flux的正确实现
解决方案
你的问题核心是Flux每个元素都触发一次文件删除,这是因为你在flatMap每个ClassB元素时都订阅了filePartMono(冷流,每次订阅都会执行一次删除逻辑)。要实现「生成Flux后仅删除一次文件,同时保留Flux返回值」,可以通过以下方式修改:
核心思路
- 先完成文件保存,保留
FilePart的引用(明确要删除的文件) - 基于保存后的文件生成
Flux<ClassB> - 给整个
Flux添加生命周期回调,在Flux结束(无论正常完成、异常终止还是被取消)时,仅执行一次文件删除操作
修改后的代码
调整FileHandlerService(可选,简化方法调用)
把saveFile的参数从Mono<FilePart>改为直接接收FilePart,避免重复处理Mono:
class FileHandlerService { public Mono<Void> saveFile(FilePart filePart) { return filePart.transferTo(Path.of(filePart.filename())); } public Mono<Void> deleteFile(FilePart filePart) { return Mono.fromRunnable(() -> { File file = new File(filePart.filename()); Files.deleteIfExists(file.toPath()); }) .subscribeOn(Schedulers.boundedElastic()); } }
修改ClassA的functionA方法
使用doFinally回调在Flux生命周期结束时执行一次删除:
class ClassA { FileHandlerService fileHandlerService; Flux<ClassB> functionA(Mono<FilePart> filePartMono) { return filePartMono // 先保存文件,同时保留FilePart实例 .flatMap(filePart -> fileHandlerService.saveFile(filePart) .then(Mono.just(filePart)) ) // 生成Flux<ClassB>,并添加删除回调 .flatMapMany(filePart -> { Flux<ClassB> items = getItems(filePart); // 当Flux结束时(无论成功/失败/取消),执行一次删除 return items.doFinally(signal -> fileHandlerService.deleteFile(filePart).subscribe() ); }); } Flux<ClassB> getItems(FilePart filePart) { // 你的原有逻辑:基于本地文件生成Flux } }
为什么这样改?
doFinally是Flux的生命周期钩子,只会在整个Flux序列结束时触发一次,不会随每个元素重复执行- 保留了
Flux<ClassB>的返回值,没有用then(then会将Flux转为Mono,不符合你的需求) - 无论Flux是正常输出所有元素、中途抛出异常还是被取消,都会执行文件删除,避免临时文件残留
内容的提问来源于stack exchange,提问作者Gopikrishna K S
相关产品推荐
相关产品推荐

