oss文件服务器分片上传官方文档参考: 分片上传 - 对象存储 OSS - 阿里云
官方文档写的更加详细,更多内容请参考官方文档文章来源:https://www.toymoban.com/news/detail-599864.html
oss分片上传流程
1.初始化分片事件,向oss服务器获取全局唯一的uploadId
- 获取uploadId,后续分片都需带上uploadId,标识同一个文件对象。
- 另外初始化操作时已经指定文件访问链接,还可以添加一些请求头,如缓存、文件私有访问控制等条件。*
2.开始切片上传
- 分片一般由前端完成,通过后端将分片上传到oss服务器,上传时也无需按照顺序上传。
- 也可由前端直接上传到oss服务器,此时后端仅需要向前端颁发凭证即可。
- 需要注意的是,在分片上传成功后需保存响应数据,留待第三步使用。*
3.分片上传完成,合并上传
- 分片上传完成后,需主动通知oss服务器合并文件。*
2.代码示例
开始前准备
依赖导入
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.13.2</version>
</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-10000
uploadPartRequest.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<PartETag> 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收费标准文章来源地址https://www.toymoban.com/news/detail-599864.html
前端组件参考:前端大文件上传 - 分片上传
到了这里,关于阿里云oss分片上传示例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!