Я использую TransferManager для загрузки каталога (включая большое количество файлов от 10k до 100k) на s3, и я обнаружил, что иногда загрузка может быть неудачной или зависает без каких-либо исключений или обработчика успеха.Журнал просто показывает, что он начал загружаться на s3, но он никогда не показывает, что он закончился или не прошел.
Я показываю свой код ниже, надеюсь, кто-то может помочь мне выяснить, что происходит не так.
@PostMapping
public ResponseEntity upload(
@RequestPart("file") @Valid
MultipartFile file) throws IOException {
try {
File dest = File.createTempFile(UUID.randomUUID().toString(), "zip");
if (!dest.getParentFile().exists()) {
Files.createDirectories(dest.getParentFile().toPath());
}
file.transferTo(dest);
CompletableFuture.supplyAsync(() -> {
try {
long size = fileUploadService
.upload(new FileInputStream(dest),uploadDescriptor.getTargetPath());
if (size <= 0) {
log.fail();
} else {
log.success();
}
} catch (FileNotFoundException e) {
log.fail();
log.error(e.getMessage());
e.printStackTrace();
}
return dest.delete();
}, executor);
} catch (IOException e) {
log.error(e.getMessage());
e.printStackTrace();
}
return ResponseEntity.accepted().build();
}
А вот это FileUploadService
:
public class FileUploadService {
private StorageService storageService;
@Autowired
public FileUploadService(StorageService storageService) {
this.storageService = storageService;
}
public long upload(InputStream inputStream, String path) {
try {
Path tempDirectory = Files.createTempDirectory(UUID.randomUUID().toString());
unzip(inputStream, tempDirectory);
long size = FileUtils.sizeOfDirectory(tempDirectory.toFile());
boolean isSuccess = storageService.storeDir(tempDirectory.toFile(), path);
FileSystemUtils.deleteRecursively(tempDirectory);
return isSuccess ? size : -1;
} catch (IOException e) {
e.printStackTrace();
log.error("failed to update to {}", path);
log.error(e.getMessage());
return -1;
}
}
}
Вот это StorageService
:
@Slf4j
public class StorageService {
private static final String SUFFIX = "/";
private S3Configuration configuration;
private final AmazonS3 s3Client;
@Autowired
public S3StorageService(S3Configuration configuration) {
this.configuration = configuration;
BasicAWSCredentials awsCreds = new BasicAWSCredentials(
configuration.getAccessKey(), configuration.getAccessSecret());
s3Client = AmazonS3ClientBuilder.standard()
.withRegion(configuration.getRegion())
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.build();
}
@Override
public boolean storeDir(File file, String fullPath) {
log.info("start upload from {} to {}", file.toString(), fullPath);
TransferManager manager = TransferManagerBuilder.standard().withS3Client(s3Client).build();
try {
MultipleFileUpload xfer = manager.uploadDirectory(configuration.getBucketName(),
fullPath, file, true);
xfer.waitForCompletion();
log.info("finish upload from {} to {}", file.toString(), fullPath);
return true;
} catch (AmazonServiceException | InterruptedException e) {
e.printStackTrace();
log.error("failed to update from {} to {}", file.toString(), fullPath);
log.error(e.getMessage());
return false;
} finally {
manager.shutdownNow(false);
}
}
}