在将文件上传到AmazonS3时,我遇到一种非常奇怪的行为。
在大多数情况下(占上传总数的97%),此代码可以完美运行。 putObject
方法的其他3%执行正确,但是之后我无法恢复该文件。它不在存储桶中。
代码如下:
@Override
public String uploadAppFileToS3(File file, Long appId, String fileName) throws IOException {
FileInputStream stream;
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(s3AccessKey, s3SecretKey);
AmazonS3 s3 = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withRegion(Regions.EU_WEST_3) //eu-west-3 EU(Paris)
.build();
String contentType = Files.probeContentType(file.toPath());
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(contentType);
stream = new FileInputStream(file);
metadata.setContentLength(file.length());
String fileS3Key = appId + "/" + fileName;
s3.putObject(s3BucketName, fileS3Key, stream, metadata);
//Clear resources
stream.close();
return fileS3Key;
}
此代码从Spring Boot端点调用:
/**
* This method will handle the file upload to Amazon S3
*/
@PostMapping("/application/upload/{id}")
@ResponseBody
public AppFileDTO uploadFile(@RequestParam("file") MultipartFile file, @PathVariable Long id,
Model model) throws IOException {
//Get the app from the database
Application app = applicationService.findById(id);
model.addAttribute("app", app);
//Store the file temporarily
File temporalFile = new File(temporalStoragePath + file.getName());
file.transferTo(temporalFile);
String fileS3Key = appFileService
.uploadAppFileToS3(temporalFile, app.getId(), file.getOriginalFilename());
//Delete the file
temporalFile.delete();
//Now create the domain object for the file and associate it to it's parent
AppFile appFile = new AppFile();
appFile.setApp(app);
appFile.setFileName(file.getOriginalFilename());
appFile.setS3Key(fileS3Key);
appFileService.create(appFile);
//Send a mail to the employees indicating that a new file has been uploaded.
emailService.sendNewFileUploadNotification(appFile);
//Create a DTO and return it to the front end
AppFileDTO appFileDTO = new AppFileDTO();
appFileDTO.setFileId(appFile.getId());
appFileDTO.setCreationTimestamp(app.getCreationDate());
appFileDTO.setFileName(file.getOriginalFilename());
return appFileDTO;
}
如您所见,在调用将文件上载到S3的服务之后,便调用了发送电子邮件的通知服务。该电子邮件发送完美,这意味着对putObject
方法的调用未引发任何异常。
如果我们看一下putObject
文档,就会发现:
Amazon S3从未存储过部分对象;如果在此通话期间 没有引发异常,整个对象已存储。
这:
客户端自动计算文件的校验和。这个 对照另一个计算一次的校验和验证校验和 数据到达Amazon S3,确保数据没有在 通过网络传输。
所以直到现在我都知道:
我已经确保在多部分请求中指定了文件名。
任何想法将不胜感激。
答案 0 :(得分:0)
我看到AWS recommends使用支持标记和重置的流,而FileInputStream不支持。 SDK可能正在尝试通过标记/重置来处理网络问题,在这种情况下,流将抛出“ java.io.IOException:不支持标记/重置”。