拓展大文件上传(分片上传、断点续传、秒传):上传阿里云OSS

上篇将大文件上传到文件服务器,本篇在上篇基础上结合阿里云api实现将大文件上传大阿里云OSS。

阿里云分片示例地址:阿里云使用分片上传的方式上传大文件_对象存储(OSS)-阿里云帮助中心

上传流程

  1. 将待上传文件按照一定大小进行分片。
  2. 使用InitiateMultipartUpload接口初始化一个分片上传任务。
  3. 使用UploadPart接口上传分片。文件切分成Part之后,文件顺序是通过上传过程中指定的partNumber来确定,所以您可以并发上传这些碎片。并发数并非越多越快,请结合自身网络状况和设备负载综合考虑。如果您希望终止上传任务,可调用AbortMultipartUpload接口,成功上传的Part会一并删除。
  4.  使用CompleteMultipartUpload接口将Part组合成一个Object。

说明:其中初始化分片上传任务会生成一个uploadId,它是分片上传事件的唯一标识,上传每个分片都需要这个标识,可以根据这个ID来发起相关的操作,如取消分片上传、查询分片上传等。

在上篇基础上实现将文件分片上传到阿里云OSS:

提供OSS工具类:


@Component
public class OSSUtil {
    private static Logger logger = LoggerFactory.getLogger(OSSUtil.class);
    @Value("${oss.endpoint.ext}")
    private String endpoint;
    @Value("${oss.accessKeyId}")
    private String accessKeyId ;
    @Value("${oss.accessKeySecret}")
    private String accessKeySecret ;
    @Value("${oss.bucketName}")
    private String bucketName ;


    private OSS ossClient;

    @PostConstruct
    public void init() {
        ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }



    /**
     * 分块上传完成获取结果
     */
    public String completePartUploadFile(String fileKey, String uploadId, List<PartETag> partETags) {
        CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest(bucketName, fileKey, uploadId,
                                                                                    partETags);
        ossClient.completeMultipartUpload(request);
        String downLoadUrl = getDownloadUrl(fileKey, bucketName);
        logger.debug("-------------- 文件的下载URL ------------" + downLoadUrl);
        return downLoadUrl;
    }


    /**
     * 分片上传
     */
    public PartETag partUploadFile(String fileKey, InputStream is, String uploadId, String fileMd5, int partNum,
                                   long partSize) {
        UploadPartRequest uploadPartRequest = new UploadPartRequest();
        uploadPartRequest.setBucketName(bucketName);
        uploadPartRequest.setUploadId(uploadId);
        uploadPartRequest.setPartNumber(partNum);
        uploadPartRequest.setPartSize(partSize);
        uploadPartRequest.setInputStream(is);
        uploadPartRequest.setKey(fileKey);
        UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
        return uploadPartResult.getPartETag();
    }

    /**
     * 初始化上传,获取UploadId
     */
    public String getUploadId(String fileKey) {
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, fileKey);
        // 初始化分片
        InitiateMultipartUploadResult unrest = ossClient.initiateMultipartUpload(request);
        // 返回uploadId,它是分片上传事件的唯一标识,您可以根据这个ID来发起相关的操作,如取消分片上传、查询分片上传等。
        String uploadId = unrest.getUploadId();
        return uploadId;
    }

   
}

分片上传时调用阿里云分片上传:

/ /分片上传
boolean flag = uploadChunkToOSS(fullFileName, fileChunkDTO);

方法调用:


    //工具类
    private final OSSUtil ossUtil;
    //临时存储PartETag---合并时候需要
     List<PartETag> partETags =  new LinkedList<>();
    //临时存储uploadId----实际应该提供获取uploadId的接口,前端调用后,每次分片上传都传过来
     private Map<String, String> map1 = new HashMap<>();

    public  Boolean uploadChunkToOSS(String fullFileName,FileChunkDTO fileChunkDTO)  {
        //必须求出redis中的PartETags,在分片合成文件中需要以此为依据,合并文件返回最终地址
        String uploadId = map1.get("uploadId");
        if (uploadId == null){
            uploadId = ossUtil.getUploadId(fullFileName);
            map1.put("uploadId",uploadId);
        }

        int sliceNo = fileChunkDTO.getChunkNumber();
        int fileSlicesNum = fileChunkDTO.getTotalChunks();
        //分片上传
        try {
            //字节流转换
            InputStream inputStream = fileChunkDTO.getFile().getInputStream();
            //每次上传分片之后,OSS的返回结果会包含一个PartETag
            PartETag partETag = ossUtil.partUploadFile(fullFileName, inputStream, uploadId,
                    fileChunkDTO.getIdentifier(), sliceNo, fileChunkDTO.getFile().getSize());
           partETags.add(partETag);
            //分片编号等于总片数的时候合并文件,如果符合条件则合并文件,否则继续等待
            if (fileSlicesNum==sliceNo) {
                //合并文件,注意:partETags必须是所有分片的所以必须存入redis,然后取出放入集合
                String url = ossUtil.completePartUploadFile(fullFileName, uploadId,
                        partETags);
                //oss地址返回后存入并清除redis
                System.out.println(url);
                partETags.clear();
            }
        } catch (Exception e) {
            
        }
        return true;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值