问题描述
我正在使用 this S3 library 将文件存储到 S3 存储桶中。
代码如下:
DocumentService.java
/**
* Persists document information in Object store
*
* @param documentDto document upload data
* @return id of uploaded document
* @throws GenericException on error
*/
@Transactional
public UUID uploadDocument(DocumentDto documentDto) throws GenericException {
validationService.validateAndThrowException(documentDto);
String uuid = randomUUID().toString()
multipartfile documentFile = documentDto.getFile();
String documentRefKey = "SFI_" + currentDate() + "/" + uuid + "/";
// Store the document in s3 bucket
s3Client.putObject(createPutDocumentFileRequest(documentFile,documentRefKey));
return uuid;
}
/**
* Creates put request for object store.
*
* @param document document
* @param documentRefKey document reference key
* @return put object request
*/
private PutObjectRequest createPutDocumentFileRequest(multipartfile document,String documentRefKey) {
S3ObjectMetadata Metadata = new S3ObjectMetadata();
Metadata.addUserMetadata("fileName",document.getFileName());
Metadata.setContentType(document.getFileType());
PutObjectRequest req = new PutObjectRequest(bucketName,documentRefKey,document.getInputStream());
req.withObjectMetadata(Metadata);
return req;
}
不知道为什么会这样。
解决方法
在您的代码中的某处,可能在 currentDate
方法中,除了提供像 ddMMyyyy
这样的日期模式之外,您似乎还在日期和日期之间包含了一个 /
字符构造 documentRefKey
S3 对象键时的 UUID。它将如下所示:
SFI_11022021/<the generated uuid>
当您将此对象放入 S3 存储桶时,AWS 会解释为它应该创建一个“类似文件夹”的结构,并按 /
字符拆分信息:
SFI_11022021
<the generated uuid>
根据 AWS documentation,例如,给定键 s3-dg.pdf
和 Development/Projects.xls
等:
控制台使用键名前缀(Development/
、Finance/
和 Private/
)和分隔符('/'
)来呈现文件夹结构。 s3-dg.pdf
键没有前缀,因此它的对象直接出现在存储桶的根级别。如果您打开 Development/
文件夹,您会在其中看到 Projects.xlsx
对象。
- Amazon S3 支持存储桶和对象,并且没有层次结构。但是,通过在对象键名称中使用前缀和分隔符,Amazon S3 控制台和 AWS 开发工具包可以推断层次结构并引入文件夹的概念。
我终于自己解决了这个问题。真正的技巧是在 key
中包含完整的文件名。
为了调试问题,我查看了我通过 S3 手动上传的文件的所有属性和元信息,并将其与以编程方式上传的文件相匹配。
这导致在 key
引用中发现不匹配。
我很惊讶文档中没有明确提到它。这是固定代码:
/**
* Persists document information in Object store
*
* @param documentDto document upload data
* @return id of uploaded document
*/
@Transactional
public UUID uploadDocument(DocumentDto documentDto) {
validationHandler.validate(documentDto);
String uuid = randomUUID().toString()
MultipartFile documentFile = documentDto.getFile();
String documentRefPath = "SFI_" + currentDate() + "/" + uuid + "/";
// Store the converted document in s3 bucket
s3Client.putObject(createPutDocumentFileRequest(documentFile,documentRefPath));
return uuid;
}
/**
* Creates put request for object store.
*
* @param targetFile document file
* @param documentRefPath document reference key
* @return put object request
*/
private PutObjectRequest createPutDocumentFileRequest(MultipartFile documentFile,String documentRefPath) {
String fileName = documentFile.getFileName();
String key = documentRefPath + fileName; // <-- the missing puzzle piece
S3ObjectMetadata metadata = new S3ObjectMetadata();
metadata.addUserMetadata("fileName",fileName);
metadata.setContentType(documentFile.getFileType());
PutObjectRequest req = new PutObjectRequest(bucketName,key,documentFile);
req.withObjectMetadata(metadata);
return req;
}