阿里云oss分片上传示例

oss文件服务器分片上传官方文档参考: 分片上传 - 对象存储 OSS - 阿里云
官方文档写的更加详细,更多内容请参考官方文档

oss分片上传流程

1.初始化分片事件,向oss服务器获取全局唯一的uploadId
  • 获取uploadId,后续分片都需带上uploadId,标识同一个文件对象。
  • 另外初始化操作时已经指定文件访问链接,还可以添加一些请求头,如缓存、文件私有访问控制等条件。*
2.开始切片上传
  • 分片一般由前端完成,通过后端将分片上传到oss服务器,上传时也无需按照顺序上传。
  • 也可由前端直接上传到oss服务器,此时后端仅需要向前端颁发凭证即可。
  • 需要注意的是,在分片上传成功后需保存响应数据,留待第三步使用。*
3.分片上传完成,合并上传
  • 分片上传完成后,需主动通知oss服务器合并文件。*

2.代码示例

开始前准备
依赖导入
<dependency><groupId>com.aliyun.ossgroupId><artifactId>aliyun-sdk-ossartifactId><version>3.13.2version>
dependency> 
sql
  • 文件上传记录表
CREATE TABLE `file_upload_record` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`filename` varchar(255) DEFAULT NULL COMMENT '文件原名称',`md5` varchar(255) DEFAULT NULL COMMENT 'md5',`upload_id` varchar(255) DEFAULT NULL COMMENT 'uploadId',`paths` varchar(255) DEFAULT NULL COMMENT '图片地址',`status` varchar(255) DEFAULT NULL COMMENT '状态:wait/succ',`upload_start_time` datetime DEFAULT NULL COMMENT '上传起始时间',`upload_end_time` datetime DEFAULT NULL COMMENT '上传结束时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=39 DEFAULT CHARSET=utf8;
  • 分片上传结果记录表
CREATE TABLE `part_upload_record` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`upload_id` varchar(255) DEFAULT NULL COMMENT '唯一上传id',`part_number` int(11) DEFAULT NULL COMMENT '当前片数',`md5` varchar(255) DEFAULT NULL COMMENT '当前片的md5值',`upload_result` varchar(255) DEFAULT NULL COMMENT '分片上传结果(json)',`upload_time` datetime DEFAULT NULL COMMENT '分片上传时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=95 DEFAULT CHARSET=utf8;
请求对象
@Data
@ApiModel("分片上传实体")
public class MultipartUploadDto {/*** 唯一上传id*/@ApiModelProperty(value = "分片上传id",required = true)@NotBlank(message = "上传id不能为空")private String uploadId;/*** 当前片数*/@ApiModelProperty(value = "当前片数",required = true)@NotNull(message = "当前片数不能为空")private int partNumber;/*** 当前片大小*/@ApiModelProperty(value = "当前片大小",required = true)@NotNull(message = "当前片大小不能为空")private long partSize;/*** 总片数*/@ApiModelProperty(value = "总片数",required = true)@NotNull(message = "总片数不能为空")private int totalPart;/*** 当前片的md5值*/@ApiModelProperty(value = "当前片的md5")private String md5;/*** 文件*/@ApiModelProperty(value = "当前片文件",required = true)@NotNull(message = "文件不能为空")private MultipartFile file;
}
获取uploadId
1.初始化 ossClient
  {// 创建OSSClient实例。ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);}
2.获取uploadId
/*** 获取文件上传id* @param fileName 文件名称* @return r*/public UploadIdRespDto getUploadId(String fileName) {// 文件名称String objectName = "multipart" + "/" + UUID.randomUUID().toString().replaceAll("-", "") + "." + getFileExtName(fileName);ObjectMetadata metadata = new ObjectMetadata();metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
//        //指定该Object的网页缓存行为。metadata.setCacheControl("no-cache");//设置文件为私有metadata.setObjectAcl(CannedAccessControlList.Private);
//        //指定该Object被下载时的名称。metadata.setContentDisposition("attachment;filename=" + fileName);// 创建InitiateMultipartUploadRequest对象。InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);// 初始化分片。InitiateMultipartUploadResult upResult = ossClient.initiateMultipartUpload(request);uploadService.addFileUploadRecord(upResult.getUploadId(), objectName, fileName);// 返回uploadId,它是分片上传事件的唯一标识。您可以根据该uploadId发起相关的操作,例如取消分片上传、查询分片上传等。log.info("获取uploadId成功,结果:{}", upResult);return UploadIdRespDto.builder().uploadId(upResult.getUploadId()).paths(objectName).prefix("https://" + bucketName + "." + endpoint.substring(8)).build();}
分片上传
    public MultipartUploadRespDto partUpload(MultipartUploadDto param) {String uploadId = param.getUploadId();// int total = param.getTotalPart();StopWatch st = new StopWatch();st.start();//封装分片上传请求UploadPartRequest uploadPartRequest = new UploadPartRequest();uploadPartRequest.setUploadId(param.getUploadId());//part大小 1-10000uploadPartRequest.setPartNumber(param.getPartNumber());uploadPartRequest.setPartSize(param.getPartSize());uploadPartRequest.setBucketName(bucketName);try {uploadPartRequest.setInputStream(param.getFile().getInputStream());} catch (IOException e) {throw new BusinessException("文件流异常");}FileUploadRecordEo uploadRecordEo = uploadService.findFileByUploadId(uploadId);if (uploadRecordEo == null) {throw new BusinessException("上传标识符异常!");}String objectName = uploadRecordEo.getPaths();uploadPartRequest.setKey(objectName);//查询该分片是否已上传boolean existPartNumber = uploadService.isExistPartNumber(uploadId, uploadPartRequest.getPartNumber());if (existPartNumber) {return MultipartUploadRespDto.builder().isUpload(1).partNumber(uploadPartRequest.getPartNumber()).uploadId(uploadPartRequest.getUploadId()).build();}// 每个分片不需要按顺序上传,甚至可以在不同客户端上传,OSS会按照分片号排序组成完整的文件。UploadPartResult uploadPartResult = null;try {uploadPartResult = ossClient.uploadPart(uploadPartRequest);} catch (OSSException e) {e.printStackTrace();throw new BusinessException("上传失败:" + e.getMessage());} catch (com.aliyun.oss.ClientException e) {e.printStackTrace();throw new BusinessException("上传失败,客户端错误:" + e.getMessage());}st.stop();log.info("{}文件第 {} 片上传成功,上传结果:{},耗时:{}", uploadId, uploadPartRequest.getPartNumber(), JSON.toJSON(uploadPartResult), st.getTotalTimeMillis());//保留分片上传接口uploadService.addPartUploadRecord(uploadPartResult.getPartETag(), param);//主动合并
//        List partTagList = uploadService.findPartTagListByUploadId(uploadId);
//
//        if (partTagList.size() == total) {
//            //上传成功
//            // 创建CompleteMultipartUploadRequest对象。
//            // 在执行完成分片上传操作时,需要提供所有有效的partETags。OSS收到提交的partETags后,会逐一验证每个分片的有效性。
//            // 当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件。
//            mergeMultipart(uploadId, objectName, partTagList);
//            uploadService.updateFileUpload(uploadId);
//        }return MultipartUploadRespDto.builder().isUpload(1).partNumber(uploadPartRequest.getPartNumber()).uploadId(uploadPartRequest.getUploadId()).build();}
合并上传
    private CompleteMultipartUploadResult mergeMultipart(String uploadId, String objectName, List<PartETag> partTagList) {try {StopWatch st = new StopWatch();st.start();CompleteMultipartUploadRequest completeMultipartUploadRequest =new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partTagList);log.info("{}文件上传完成,开始合并,partList:{}", uploadId, JSON.toJSON(partTagList));// 完成分片上传。CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);st.stop();log.info("{}文件上传完成,上传结果:{},耗时:{}", uploadId, JSON.toJSON(completeMultipartUploadResult), st.getTotalTimeMillis());return completeMultipartUploadResult;} catch (OSSException e) {e.printStackTrace();throw new BusinessException("合并失败:" + e.getMessage());} catch (com.aliyun.oss.ClientException e) {e.printStackTrace();throw new BusinessException("合并失败,客户端异常:" + e.getMessage());}}public CompleteMultipartUploadResult completeMultipartUpload(String uploadId) {FileUploadRecordEo uploadRecordEo = uploadService.findFileByUploadId(uploadId);if (uploadRecordEo == null) {throw new BusinessException("上传标识符异常!");}List<PartETag> partTagList = uploadService.findPartTagListByUploadId(uploadId);uploadService.updateFileUpload(uploadId);return mergeMultipart(uploadId, uploadRecordEo.getPaths(), partTagList);}

其他说明(视频截帧)

oss服务器提供了视频截帧功能,只需要在视频连接后拼上一段参数就能获取视频封面,
x-oss-process=video/snapshot,t_1000,f_jpg,w_0,h_0,m_fast,ar_auto
参数说明:
视频截帧参数说明
原始文档地址: 视频截帧
另外需要注意是,视频截帧功能是收费的,收费标准请参考oss收费标准

前端组件参考:前端大文件上传 - 分片上传


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部