阿里云视频点播AWS原生SDK上传

功能介绍

阿里云视频点播支持使用AWS原生SDK进行媒资文件的上传,默认使用分片上传,最大支持48.8TB的单个文件,且支持断点续传,旨在让客户方便、快速实现媒体文件的上传。

准备工作

请确认你已开通了视频点播服务,如未开通,请参考开通服务。

上传步骤

访问点播SDK获取上传地址和上传凭证信息,包含如下字段:

变量名含义videoId媒资ID,token过期后可用于刷新上传地址和凭证uploadUrl上传链接,可直接put上传小文件authTokenBase64编码后的上传凭证

使用Base64解析上传凭证(authToken),得到OSS的上传地址和授权信息

authToken字段Base64解码后,得到JSON格式字符串,包含字段如下:

变量名含义accessKey点播系统aksecretKey点播系统sksessionToken鉴权tokenexpiration过期时间endpointOSS区域地址regionOSS区域bucketOSSBucket名称objectKey媒体文件OSS位置

调用AWSSDK将视频文件上传至指定bucket的指定位置,(使用解析后的上传地址和授权信息初始化AWS客户端,不要使用自己的AccessKey等信息)。

代码实现

核心代码实现共分4步:

1.使用AKSK初始化VOD客户端
2.获取视频上传地址和凭证
3.解析并使用上传凭证和地址初始化AWS客户端
4.上传本地文件

使用AWSSDK在服务端上传,可参考如下版本:

JAVA上传示例

安装依赖

dependencygroupIdcom.amazonaws/groupIdartifactIdaws-java-sdk-s3/artifactIdversion1.11.136/version/dependency分片上传

对于大文件,可以切分成片上传,分片上传(MultipartUpload)分为如下3个步骤:
1.初始化一个分片上传任务(InitiateMultipartUpload)
调用ossClient.initiateMultipartUpload方法返回OSS创建的全局唯一的uploadId。

2.逐个或并行上传分片(UploadPart)
调用ossClient.uploadPart方法上传分片数据。

注意:
A.OSS会将服务器端收到Part数据的MD5值放在ETag头内返回给用户。
B.Part号码的范围是1~10000。如果超出这个范围,将返回400,错误码:TooManyParts。
C.每次上传part时都要把流定位到此次上传块开头所对应的位置。
D.每次上传part之后,OSS的返回结果是一个UploadPartResult对象,他是包含上传块的ETag与块编号(PartNumber)的组合.
E.在后续完成分片上传的步骤中会用到它,因此需要将其保存起来。一般来讲将这些UploadPartResult对象保存到List中。

3.完成分片上传(CompleteMultipartUpload)
所有分片上传完成后,调用ossClient.completeMultipartUpload方法将所有分片合并成完整的文件。
在执行该操作时,需要提供所有有效的分片列表(包括分片号和分片ETAG);OSS收到提交的分片列表后,会逐一验证每个分片的有效性。当所有的数据Part验证通过后,OSS将把这些分片组合成一个完整的Object。

完整示例

/Createdon一月06,2020.@authorZhangxi19/publicclassUpload{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(Upload.class);publicstaticvoidmain(String[]args){//通过点播sdkvodClient.createVideoUploadTask或vodClient.refreshVideoUploadTask,从结果中可获取上传凭证authToken,//用base64解析后可得到具体的上传凭证,该凭证可用于创建aws的客户端,完成分片上传Stringregion="region";Stringendpoint="endpoint";Stringbucket="bucket";StringaccessKey="accessKey";StringsecretKey="secretKey";Stringtoken="token";StringobjectKey="objectKey";StringlocalFile="localFile";multipartUpload(region,endpoint,accessKey,secretKey,token,bucket,objectKey,localFile);}publicstaticvoidmultipartUpload(Stringregion,Stringendpoint,StringaccessKey,StringsecretKey,Stringtoken,Stringbucket,StringobjectKey,StringlocalFile){AmazonS3ossClient=initAwsClient(region,endpoint,accessKey,secretKey,token,Protocol.HTTP);try{FilepartFile=newFile(localFile);Stringmd5=Md5Utils.md5AsBase64(partFile);logger.info("md5={}",md5);//初始化分片上传InitiateMultipartUploadRequestpartRequest=newInitiateMultipartUploadRequest(bucket,objectKey);ObjectMetadataobjectMetadata=newObjectMetadata();//以具体视频源为准objectMetadata.setContentType("video/mp4");objectMetadata.setContentMD5(md5);partRequest.setObjectMetadata(objectMetadata);InitiateMultipartUploadResultinitiateMultipartUpload=ossClient.initiateMultipartUpload(partRequest);Stringkey=initiateMultipartUpload.getKey();StringuploadId=initiateMultipartUpload.getUploadId();StringbucketName=initiateMultipartUpload.getBucketName();logger.info("InitiateMultipartUploadResult,bucket={},key={},uploadId={}",bucket,key,uploadId);//根据实际需求确定分片大小finalintpartSize=102410245;intpartCount=(int)(partFile.length()/partSize);if(partFile.length()%partSize!=0){partCount++;}//创建对象的Etag列表,并取回每个分片的Etag。ListPartETagpartETagList=newArrayList();for(inti=0;ipartCount;i++){FileInputStreamfis=newFileInputStream(partFile);longskipBytes=partSizei;fis.skip(skipBytes);longsize=Math.min(partSize,partFile.length()-skipBytes);logger.info("partSize={}",size);UploadPartRequestuploadPartRequest=newUploadPartRequest();uploadPartRequest.setBucketName(bucketName);uploadPartRequest.setKey(key);uploadPartRequest.setUploadId(uploadId);uploadPartRequest.setInputStream(fis);uploadPartRequest.setPartSize(size);uploadPartRequest.setPartNumber(i+1);//上传分片并将返回的Etag加入列表中UploadPartResultuploadPartResult=ossClient.uploadPart(uploadPartRequest);PartETagpartETag=uploadPartResult.getPartETag();partETagList.add(partETag);logger.info("uploadPartResult={}",JSON.toJSON(uploadPartResult));fis.close();}Collections.sort(partETagList,newComparatorPartETag(){publicintcompare(PartETagp1,PartETagp2){returnp1.getPartNumber()-p2.getPartNumber();}});//完成上传CompleteMultipartUploadRequestcompleteMultipartUploadRequest=newCompleteMultipartUploadRequest(bucket,objectKey,uploadId,partETagList);MapString,StringcustomRequestHeaders=completeMultipartUploadRequest.getCustomRequestHeaders();CompleteMultipartUploadResultuploadResult=ossClient.completeMultipartUpload(completeMultipartUploadRequest);ossClient.shutdown();logger.info("CompleteMultipartUploadResult={},customRequestHeaders={}",JSON.toJSON(uploadResult),customRequestHeaders);}catch(IOExceptione){e.printStackTrace();}}publicstaticAmazonS3initAwsClient(Stringregion,Stringendpoint,StringaccessKey,StringsecretKey,Stringtoken,com.amazonaws.Protocolprotocol){BasicSessionCredentialsbasicSessionCredentials=newBasicSessionCredentials(accessKey,secretKey,token);ClientConfigurationconfig=newClientConfiguration();config.setProtocol(protocol);AwsClientBuilder.EndpointConfigurationendpointConfig=newAwsClientBuilder.EndpointConfiguration(endpoint,region);AWSCredentialsProviderawsCredentialsProvider=newAWSStaticCredentialsProvider(basicSessionCredentials);returnAmazonS3Client.builder().withEndpointConfiguration(endpointConfig).withClientConfiguration(config).withCredentials(awsCredentialsProvider).disableChunkedEncoding().withPathStyleAccessEnabled(true).build();}}