当前位置:   article > 正文

基于Amazon S3的通用封装oss-spring-boot-starter,支持前端分片直传

oss-spring-boot-starter

前段时间使用minio-java封装了一个 minio-spring-boot-starter,但是有局限性,不能很好的支持各个云服务厂商的OSS服务,为此,利用 aws-java-sdk-s3 做一个统一的封装,兼容S3 协议的通用文件存储工具类 ,支持 兼容S3 协议的云存储

  • MINIO
  • 阿里云
  • 华为云
  • 腾讯云
  • 京东云
  • 七牛云

maven

目前最新版本:3.0.0

项目源码:GitHub腾讯云Coding

版本更新日志查询,可查看项目下 UPDATE.md 文件

适配 SpringBoot3.x,也支持 SpringBoot2.x

最新版本查询:https://central.sonatype.com/artifact/com.kangaroohy/oss-spring-boot-starter

<dependency>
    <groupId>com.kangaroohy</groupId>
    <artifactId>oss-spring-boot-starter</artifactId>
    <version>${lastVersion}</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

使用方法

配置文件

kangaroohy:
    oss:
      endpoint: https://demo.kangaroohy.com
      access-key: admin
      secret-key: admin123
  • 1
  • 2
  • 3
  • 4
  • 5

path-style-access: false 时,也就是 virtual-host-style

  • https://{bucketName}.{endpoint}
  • 如:https://{bucketName}.demo.kangaroohy.com

path-style-access: true 时

  • https://{endpoint}/{bucketName}
  • 如:https://demo.kangaroohy.com/{bucketName}

代码使用

注入OssTemplate,调用相关方法即可

    @Autowired
    private OssTemplate ossTemplate;

    @PostMapping("/upload")
    @Operation(summary = "普通上传")
    public RestResult<String> upload(MultipartFile file) throws IOException {
        ossTemplate.putObject(bucketName, file.getOriginalFilename(), file.getContentType(), file.getInputStream());
        return RestResult.ok();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

封装方法不满足时,可自行注入 AmazonS3 ,调用原始方法

    @Autowired
    private AmazonS3 amazonS3;
  • 1
  • 2

前端PUT直传

后端,获取上传的url,前端 PUT 方式直接请求

注:七牛云、腾讯云等云服务器厂商可能需要配置跨域

    @GetMapping("/upload-url")
    @Operation(summary = "获取Put直传地址")
    public RestResult<String> uploadUrl(@RequestParam String fileName) {
        String url = ossTemplate.getPresignedObjectPutUrl(fileName);
        return RestResult.ok(url);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

分片上传

推荐方式二

方式一 后端接收分片,再上传oss服务器

思路:请求后端获取分片标识,前端分片,请求后端接口上传分片,上传完成,再请求合并分片的接口

    @GetMapping("/upload-id")
    @Operation(summary = "获取分片upload id")
    public RestResult<String> uploadId(@RequestParam String fileName, @RequestParam String contentType) {
        InitiateMultipartUploadResult uploadResult = ossTemplate.initiateMultipartUpload(ossTemplate.getBucketName(), fileName, contentType);    
        return RestResult.ok(uploadResult.getUploadId());
    }

    @PutMapping("/upload-part")
    @Operation(summary = "分片上传")
    public RestResult<String> uploadPart(@RequestPart MultipartFile file, @RequestPart @Validated UploadPartInfoBO partInfo) {
        byte[] md5s;
        long partSize;
        ByteArrayInputStream inputStream;
        try {
            md5s = MessageDigest.getInstance("MD5").digest(file.getBytes());
            partSize = file.getSize();
            inputStream = new ByteArrayInputStream(file.getBytes());
        } catch (NoSuchAlgorithmException | IOException e) {
            throw new FailException("分块上传MD5加密出错");
        }
        ossTemplate.uploadPart(partInfo.getUploadId(), partInfo.getFileName(), Base64.encodeAsString(md5s), partInfo.getPartNumber(), partSize, inputStream);
        return RestResult.ok();
    }

    @GetMapping("/merge-part")
    @Operation(summary = "分片上传完成合并")
    public RestResult<String> mergePart(@RequestParam String fileName, @RequestParam String uploadId) {
        ossTemplate.completeMultipartUpload(fileName, uploadId);
        return RestResult.ok(ossTemplate.getGatewayUrl(fileName));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
@Data
public class UploadPartInfoBO {

    @NotNull(message = "uploadId is required")
    private String uploadId;

    @NotNull(message = "fileName is required")
    private String fileName;

    @NotNull(message = "partNumber is required")
    private Integer partNumber;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述

方式二 前端直传oss服务器

注:云服务商oss可能需要配置跨域

思路:前端请求后端,获取各个分片预签名 url,直接 PUT 方式请求上传 oss 服务器,上传完成,请求后端合并分片

    @GetMapping("/part-url")
    @Operation(summary = "获取分片直传地址")
    public RestResult<MultiPartUploadInfo> partUrl(@RequestParam String fileName, @RequestParam int partSize, @RequestParam String contentType) {
        MultiPartUploadInfo uploadInfo = ossTemplate.getPresignedMultipartUploadUrls(fileName, partSize, contentType);
        return RestResult.ok(uploadInfo);
    }

    @GetMapping("/merge-part")
    @Operation(summary = "分片上传完成合并")
    public RestResult<String> mergePart(@RequestParam String fileName, @RequestParam String uploadId) {
        ossTemplate.completeMultipartUpload(fileName, uploadId);
        return RestResult.ok(ossTemplate.getGatewayUrl(fileName));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/707057
推荐阅读
相关标签
  

闽ICP备14008679号