AWS S3预签名方上传文件

前文

网上有很多S3的上传示例,但都没有一个很完整的流程。这里记录一下使用ajva SDKV2实现的步骤

控制台配置

注意配置跨域。添加put请求跨域

上传流程

前端 服务端 S3 获取预签名url 创建预签名url 返回上传url 返回url 通过url上传文件 更新数据 前端 服务端 S3

后端代码

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不然视频不是打开而是下载

  • 58
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值