我正在使用Spring WebFlux开发API REST,但是上传文件时遇到问题。它们已存储,但是我没有得到期望的返回值。
这就是我的工作
我希望返回文件名,但是客户端会得到一个空字符串。
控制器代码
@PostMapping(value = "/muscles/{id}/image")
public Flux<String> updateImage(@PathVariable("id") String id, @RequestBody Flux<Part> file) {
log.info("REST request to update image to Muscle");
return storageService.saveFiles(file);
}
StorageService
public Flux<String> saveFiles(Flux<Part> parts) {
log.info("StorageService.saveFiles({})", parts);
return
parts
.filter(p -> p instanceof FilePart)
.cast(FilePart.class)
.flatMap(file -> saveFile(file));
}
private Mono<String> saveFile(FilePart filePart) {
log.info("StorageService.saveFile({})", filePart);
String filename = DigestUtils.sha256Hex(filePart.filename() + new Date());
Path target = rootLocation.resolve(filename);
try {
Files.deleteIfExists(target);
File file = Files.createFile(target).toFile();
return filePart.transferTo(file)
.map(r -> filename);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
答案 0 :(得分:3)
FilePart.transferTo()
返回Mono<Void>
,它在操作完成时发出信号-这意味着反应性Publisher
将仅发布onComplete
/ onError
信号,并且将在此之前不要发布任何值。
这意味着map
操作从未执行过,因为它只给出了源发布的元素。
您可以返回文件名,并仍然链接反应式运算符,如下所示:
return part.transferTo(file).thenReturn(part.filename());
禁止在反应式管道及其even throws an exception at runtime as of Reactor 3.2中使用block
运算符。
使用subscribe
作为替代也是不好的,因为subscribe
将使传输过程与请求处理脱钩,从而使传输过程以不同的执行顺序进行。这意味着您的服务器可以完成处理请求并关闭HTTP连接的工作,而另一部分仍在尝试读取文件部分以将其复制到磁盘上。在运行时这可能会以微妙的方式失败。
答案 1 :(得分:0)
FilePart.transferTo()返回Mono
private Mono<String> saveFile(FilePart filePart) {
log.info("StorageService.saveFile({})", filePart);
String filename = DigestUtils.sha256Hex(filePart.filename() + new Date());
Path target = rootLocation.resolve(filename);
try {
Files.deleteIfExists(target);
File file = Files.createFile(target).toFile();
return filePart
.transferTo(file)
.doOnSuccess(data -> log.info("do something..."))
.thenReturn(filename);
} catch (IOException e) {
throw new RuntimeException(e);
}
}