如何使用 Webflux 上传多个文件?
How to upload multiple files using Webflux?
如何使用Webflux上传多个文件?
我发送内容类型为 multipart/form-data
的请求,正文包含一个 部分 ,其值是一组文件。
为了处理单个文件,我按如下方式进行:
Mono<MultiValueMap<String, Part> body = request.body(toMultipartData());
body.flatMap(map -> FilePart part = (FilePart) map.toSingleValueMap().get("file"));
但是如何为多个文件做呢?
PS。还有其他方法可以在 webflux 中上传一组文件吗?
您可以使用 Flux 和 return Flux
迭代 hashmap
Flux.fromIterable(hashMap.entrySet())
.map(o -> hashmap.get(o));
并且它将作为一个包含文件部分
的数组发送
以下是使用 WebFlux 上传多个文件的工作代码。
@RequestMapping(value = "upload", method = RequestMethod.POST)
Mono<Object> upload(@RequestBody Flux<Part> parts) {
return parts.log().collectList().map(mparts -> {
return mparts.stream().map(mmp -> {
if (mmp instanceof FilePart) {
FilePart fp = (FilePart) mmp;
fp.transferTo(new File("c:/hello/"+fp.filename()));
} else {
// process the other non file parts
}
return mmp instanceof FilePart ? mmp.name() + ":" + ((FilePart) mmp).filename() : mmp.name();
}).collect(Collectors.joining(",", "[", "]"));
});
};
关键是用toParts代替toMultipartData,这样更简单。这是与 RouterFunctions.
一起使用的示例
private Mono<ServerResponse> working2(final ServerRequest request) {
final Flux<Void> voidFlux = request.body(BodyExtractors.toParts())
.cast(FilePart.class)
.flatMap(filePart -> {
final String extension = FilenameUtils.getExtension(filePart.filename());
final String baseName = FilenameUtils.getBaseName(filePart.filename());
final String format = LocalDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE);
final Path path = Path.of("/tmp", String.format("%s-%s.%s", baseName, format, extension));
return filePart.transferTo(path);
});
return ServerResponse
.ok()
.contentType(APPLICATION_JSON_UTF8)
.body(voidFlux, Void.class);
}
我已经找到了一些解决方案。
假设我们发送一个带有参数 files 的 http POST 请求,其中包含我们的文件。
注意回复随意
带有 RequestPart 的 RestController
@PostMapping("/upload")
public Mono<String> process(@RequestPart("files") Flux<FilePart> filePartFlux) {
return filePartFlux.flatMap(it -> it.transferTo(Paths.get("/tmp/" + it.filename())))
.then(Mono.just("OK"));
}
RestController with ModelAttribute
@PostMapping("/upload-model")
public Mono<String> processModel(@ModelAttribute Model model) {
model.getFiles().forEach(it -> it.transferTo(Paths.get("/tmp/" + it.filename())));
return Mono.just("OK");
}
class Model {
private List<FilePart> files;
//getters and setters
}
HandlerFunction 的函数方式
public Mono<ServerResponse> upload(ServerRequest request) {
Mono<String> then = request.multipartData().map(it -> it.get("files"))
.flatMapMany(Flux::fromIterable)
.cast(FilePart.class)
.flatMap(it -> it.transferTo(Paths.get("/tmp/" + it.filename())))
.then(Mono.just("OK"));
return ServerResponse.ok().body(then, String.class);
}
希望对你有帮助
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public JSON fileUpload(@RequestPart FilePart file)throws Exception{
OSS ossClient = new OSSClientBuilder().build(APPConfig.ENDPOINT, APPConfig.ALI_ACCESSKEYID, APPConfig.ALI_ACCESSSECRET);
File f = null;
String url;
try {
String suffix = file.filename();
String fileName = "images/" + file.filename();
Path path = Files.createTempFile("tempimg", suffix.substring(1, suffix.length()));
file.transferTo(path);
f = path.toFile();
ossClient.putObject(APPConfig.BUCKETNAME, fileName, new FileInputStream(f));
Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
url = ossClient.generatePresignedUrl(APPConfig.BUCKETNAME, fileName, expiration).toString();
}finally {
f.delete();
ossClient.shutdown();
}
return JSONUtils.successResposeData(url);
}
如何使用Webflux上传多个文件?
我发送内容类型为 multipart/form-data
的请求,正文包含一个 部分 ,其值是一组文件。
为了处理单个文件,我按如下方式进行:
Mono<MultiValueMap<String, Part> body = request.body(toMultipartData());
body.flatMap(map -> FilePart part = (FilePart) map.toSingleValueMap().get("file"));
但是如何为多个文件做呢?
PS。还有其他方法可以在 webflux 中上传一组文件吗?
您可以使用 Flux 和 return Flux
迭代 hashmapFlux.fromIterable(hashMap.entrySet())
.map(o -> hashmap.get(o));
并且它将作为一个包含文件部分
的数组发送以下是使用 WebFlux 上传多个文件的工作代码。
@RequestMapping(value = "upload", method = RequestMethod.POST)
Mono<Object> upload(@RequestBody Flux<Part> parts) {
return parts.log().collectList().map(mparts -> {
return mparts.stream().map(mmp -> {
if (mmp instanceof FilePart) {
FilePart fp = (FilePart) mmp;
fp.transferTo(new File("c:/hello/"+fp.filename()));
} else {
// process the other non file parts
}
return mmp instanceof FilePart ? mmp.name() + ":" + ((FilePart) mmp).filename() : mmp.name();
}).collect(Collectors.joining(",", "[", "]"));
});
};
关键是用toParts代替toMultipartData,这样更简单。这是与 RouterFunctions.
一起使用的示例private Mono<ServerResponse> working2(final ServerRequest request) {
final Flux<Void> voidFlux = request.body(BodyExtractors.toParts())
.cast(FilePart.class)
.flatMap(filePart -> {
final String extension = FilenameUtils.getExtension(filePart.filename());
final String baseName = FilenameUtils.getBaseName(filePart.filename());
final String format = LocalDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE);
final Path path = Path.of("/tmp", String.format("%s-%s.%s", baseName, format, extension));
return filePart.transferTo(path);
});
return ServerResponse
.ok()
.contentType(APPLICATION_JSON_UTF8)
.body(voidFlux, Void.class);
}
我已经找到了一些解决方案。 假设我们发送一个带有参数 files 的 http POST 请求,其中包含我们的文件。
注意回复随意
带有 RequestPart 的 RestController
@PostMapping("/upload") public Mono<String> process(@RequestPart("files") Flux<FilePart> filePartFlux) { return filePartFlux.flatMap(it -> it.transferTo(Paths.get("/tmp/" + it.filename()))) .then(Mono.just("OK")); }
RestController with ModelAttribute
@PostMapping("/upload-model") public Mono<String> processModel(@ModelAttribute Model model) { model.getFiles().forEach(it -> it.transferTo(Paths.get("/tmp/" + it.filename()))); return Mono.just("OK"); } class Model { private List<FilePart> files; //getters and setters }
HandlerFunction 的函数方式
public Mono<ServerResponse> upload(ServerRequest request) { Mono<String> then = request.multipartData().map(it -> it.get("files")) .flatMapMany(Flux::fromIterable) .cast(FilePart.class) .flatMap(it -> it.transferTo(Paths.get("/tmp/" + it.filename()))) .then(Mono.just("OK")); return ServerResponse.ok().body(then, String.class); }
希望对你有帮助
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public JSON fileUpload(@RequestPart FilePart file)throws Exception{
OSS ossClient = new OSSClientBuilder().build(APPConfig.ENDPOINT, APPConfig.ALI_ACCESSKEYID, APPConfig.ALI_ACCESSSECRET);
File f = null;
String url;
try {
String suffix = file.filename();
String fileName = "images/" + file.filename();
Path path = Files.createTempFile("tempimg", suffix.substring(1, suffix.length()));
file.transferTo(path);
f = path.toFile();
ossClient.putObject(APPConfig.BUCKETNAME, fileName, new FileInputStream(f));
Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
url = ossClient.generatePresignedUrl(APPConfig.BUCKETNAME, fileName, expiration).toString();
}finally {
f.delete();
ossClient.shutdown();
}
return JSONUtils.successResposeData(url);
}