前文
网上有很多S3的上传示例,但都没有一个很完整的流程。这里记录一下使用ajva SDKV2实现的步骤
控制台配置
注意配置跨域。添加put请求跨域
上传流程
后端代码
maven导入
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.19.26</version>
</dependency>
service
public class AmazonService {
private static final Logger log = LoggerFactory.getLogger(AmazonService.class);
private S3Presigner presigner;
@PostConstruct
private void initializeAmazon() {
AwsCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(AwsBasicCredentials.create("accessKey", "secretKey"));
presigner = S3Presigner.builder()
.region(Region.of("region"))
.credentialsProvider(credentialsProvider)
.build();
}
public String createPresignedUrl(String keyName, Map<String, String> metadata) {
AwsRequestOverrideConfiguration override = AwsRequestOverrideConfiguration.builder()
.putRawQueryParameter("x-amz-acl", ObjectCannedACL.PUBLIC_READ.toString())
.build();
PutObjectRequest objectRequest = PutObjectRequest.builder()
.bucket("bucketName")
.key(keyName)
.metadata(metadata)
.overrideConfiguration(override)
.build();
PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder()
.signatureDuration(Duration.ofMinutes(10)) // The URL expires in 10 minutes.
.putObjectRequest(objectRequest)
.build();
PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest);
String myURL = presignedRequest.url().toString();
log.info("Presigned URL to upload a file to: [{}]", myURL);
log.info("HTTP method: [{}]", presignedRequest.httpRequest().method());
return presignedRequest.url().toExternalForm();
}
}
controller
@GetMapping("/getUploadUrl")
public CommonResult<String> getUploadUrl(@RequestParam("keyName") String keyName){
Map<String, String> metadata = new HashMap<>();
return CommonResult.success(this.amazonService.createPresignedUrl(keyName,metadata));
}
前端代码
<input type="file" accept="video/*" @change="handleSecondVideoUploadAll" multiple />
async handleSecondVideoUploadAll(event) {
const { files } = event.target;
const tempFiles = Array.from(files);
if (tempFiles) {
//多文件
Promise.all(tempFiles.map(async file=>{
const result = await getUploadUrl("test/"+file.name);//获取url
return this.put(result.data, file,"test/"+file.name);//
})).then(results => {
// 在这里执行下一步操作
//....执行更新数据操作
console.log("上传成功")
}).catch(error => {
// 处理任何一个promise被reject的情况
console.error('Error:', error);
});
}
},
async put(url, data,keyName) {
return new Promise(async (resolve,reject) => {
const formData = new FormData();
const bold = new Blob([data])
formData.append('video', data);
const response = await fetch(url, {
method: 'PUT',
headers: { "Content-Type": "video/mp4" },
body: bold // 二进制数据
});
if (!response.ok) {
reject(new Error(`HTTP error! status: ${response.status}`)) ;
}
resolve(keyName)
})
}
遇到的坑
1.文档难找,以下是相关的文档:
官方文档示例
相关博客
2.签名不匹配,检查请求是否为put请求,accessKey与secretKey是否正确
3.上传文件设置为public-read,使用AwsRequestOverrideConfiguration 配置而不是 PutObjectRequest.acl(“public-read”)
4.前端上传时要添加headers不然视频不是打开而是下载