#java #spring-webflux
Вопрос:
Я загружаю файлы в S3 с помощью Spring WebFlux, ниже приведен мой код
FileController.java
public Mono<UploadResponse> upload(@RequestPart("file") Mono<FilePart> partMono) {
return partMono
.doOnNext(filePart -> log.info("Received File : " filePart.filename()))
.flatMap(filePart -> fileService.uploadFile(filePart));
}
FileService.java
public Mono<UploadResponse> uploadFile(FilePart filePart) {
try {
log.info("Thread in ImageService: {}", Thread.currentThread().getName());e
String fileName = filePart.filename();
var fileUrl = fileRepository.getUrl(fileName);
var targetFile = File.createTempFile(filePart.filename(), "");
return filePart.transferTo(targetFile)
.doOnSuccess(x -> {
log.info("Thread in Mono: {}", Thread.currentThread().getName());
fileRepository.uploadFile(targetFile, fileName);
log.info("Delete file {}", targetFile.getAbsolutePath());
targetFile.delete();
})
.thenReturn(UploadResponse.builder()
.fileName(fileName)
.url(fileUrl)
.build());
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new FileUploadException("File upload fail. Reason: " e.getMessage(), e);
}
}
S3FileRepository.java
public UploadResponse uploadFile(File file, String fileName) {
log.info("Uploading {} to S3 bucket {}...", fileName, bucketName);
try {
var fileUrl = s3Client.getUrl(bucketName, fileName).toExternalForm();
var request = new PutObjectRequest(bucketName, fileName, file);
if(cannedAcl != null) {
request.withCannedAcl(cannedAcl);
}
s3Client.putObject(new PutObjectRequest(bucketName, fileName, file));
var response = UploadResponse.builder()
.fileName(fileName)
.url(fileUrl)
.build();
return response;
} catch (AmazonServiceException e) {
log.error("Upload of {} to S3 bucket {} FAILED", fileName, bucketName);
throw e;
}
}
public String getUrl(String fileName) {
return s3Client.getUrl("mybucket", fileName).toExternalForm();
}
В методе загрузки файловой службы я не вызываю никаких методов подписки на файловую часть, но он все равно запускается и вызывает метод FileRepository, почему это работает? И со стороны клиента мне нужно немного подождать, чтобы получить результат, как сделать мою загрузку полностью асинхронной и немедленно вернуть результат?
Комментарии:
1. где
fileRepository.getUrl
код? а такжеFile.createTempFile
являетсяblocking
вызовом. Все файловые операции блокируются.2. что я должен сделать, чтобы избежать блокировки кода?
3. Погуглите или прочитайте справочную документацию по реактору.