更新时间:2024-10-24 GMT+08:00
Java
分段上传Java语言的示例代码,如下所示:
/* * Copyright (c) Huawei Technologies Co., Ltd. 2019-2022. All rights reserved. */ package com.huaweicloud.vod; import com.huaweicloud.sdk.core.auth.BasicCredentials; import com.huaweicloud.sdk.core.auth.ICredential; import com.huaweicloud.sdk.core.exception.ConnectionException; import com.huaweicloud.sdk.core.exception.RequestTimeoutException; import com.huaweicloud.sdk.core.exception.ServiceResponseException; import com.huaweicloud.sdk.vod.v1.VodClient; import com.huaweicloud.sdk.vod.v1.model.ConfirmAssetUploadReq; import com.huaweicloud.sdk.vod.v1.model.ConfirmAssetUploadRequest; import com.huaweicloud.sdk.vod.v1.model.ConfirmAssetUploadResponse; import com.huaweicloud.sdk.vod.v1.model.CreateAssetByFileUploadReq; import com.huaweicloud.sdk.vod.v1.model.CreateAssetByFileUploadRequest; import com.huaweicloud.sdk.vod.v1.model.CreateAssetByFileUploadResponse; import com.huaweicloud.sdk.vod.v1.model.ShowAssetTempAuthorityRequest; import com.huaweicloud.sdk.vod.v1.model.ShowAssetTempAuthorityResponse; import com.huaweicloud.sdk.vod.v1.region.VodRegion; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.StringUtils; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.MessageDigest; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.List; import java.util.TimeZone; /** * 分段上传示例 */ public class PartUploadDemo { // 设置缓冲区大小,每次读取文件分段的大小,根据情况自行设定 public static final int bufferSize = 1024 * 1024; // 1MB // 区域 public static final String REGION_NORTH4 = "cn-north-4"; public static final String REGION_NORTH1 = "cn-north-1"; public static final String REGION_EAST2 = "cn-east-2"; // ak/sk private static final String AK = ""; private static final String SK = ""; public static void main(String[] args) { // 本地要上传的媒资路径 String filePath = ""; PartUploadDemo uploadDemo = new PartUploadDemo(); // 上传媒资文件 uploadDemo.uploadPartFile(filePath); } /** * 分段上传 * @param filePath 上传文件的本地路径 */ public void uploadPartFile(String filePath) { // 校验一下文件路径和文件 File file = validFile(filePath); try { String fileName = file.getName(); // 此处仅以MP4文件示例,其他格式可参考官网说明 String fileType = "MP4"; String fileContentType = "video/mp4"; // FileInfo fileInfo = new FileInfo(filePath, file); // 1.初始化鉴权并获取vodClient VodClient vodClient = this.createVodClient(); System.out.println("开始创建媒资:" + file.getName()); // 2.创建点播媒资 CreateAssetByFileUploadReq reqbody = this.buildFileUploadReq(fileName, fileType, null, null); CreateAssetByFileUploadResponse assetResponse = this.createAssetByFileUpload(vodClient, reqbody); // 3.获取初始化上传任务授权 ShowAssetTempAuthorityResponse initAuthResponse = this.initPartUploadAuthority(vodClient, assetResponse, fileContentType); // 4.初始化上传任务 String uploadId = this.initPartUpload(initAuthResponse.getSignStr(), fileContentType); // 文件分段计数 int partNumber = 1; // 缓冲区 byte[] fileByte = new byte[bufferSize]; // 记录读取的长度 int readLength = 0; // 7.读取文件内容, 循环5-6步上传所有分段 FileInputStream fis = new FileInputStream(file); // MD5 MessageDigest md = MessageDigest.getInstance("MD5"); while ((readLength = fis.read(fileByte)) > 0) { // 读取的长度小于缓冲区长度,复制有效长度内数据,用于最后一段 if(readLength < bufferSize) { fileByte = Arrays.copyOf(fileByte, readLength); } // 先md5,再base64 encode byte[] digest = md.digest(fileByte); String contentMd5 = new String(Base64.encodeBase64(digest)); System.out.println("该文件第"+(partNumber)+"段MD5为: " + contentMd5); // 5.获取上传分段的授权 ShowAssetTempAuthorityResponse partUploadAuthorityResponse = this.getPartUploadAuthority(vodClient, fileContentType, assetResponse, contentMd5, uploadId, partNumber); // 6.上传分段 this.uploadPartFile(partUploadAuthorityResponse.getSignStr(), fileByte, contentMd5); // 段号自增 partNumber++; } fis.close(); // 8.获取已上传分段的授权 ShowAssetTempAuthorityResponse listPartUploadAuthorityResponse = this.listUploadedPartAuthority(vodClient, assetResponse, uploadId); // 9.获取已上传的分段 String partInfo = this.listUploadedPart(listPartUploadAuthorityResponse.getSignStr()); // 10.获取合并段授权 ShowAssetTempAuthorityResponse mergePartUploadAuthorityResponse = this.mergeUploadedPartAuthority(vodClient, assetResponse, uploadId); // 11.合并上传分段 this.mergeUploadedPart(mergePartUploadAuthorityResponse.getSignStr(), partInfo); // 12.确认媒资上传 this.confirmUploaded(vodClient, assetResponse); System.out.println("创建媒资结束 assetId:" + assetResponse.getAssetId()); } catch (ServiceResponseException e) { e.printStackTrace(); System.out.println(String.valueOf(e.getHttpStatusCode())); System.out.println(e.getRequestId()); System.out.println(e.getErrorCode()); System.out.println(e.getErrorMsg()); } catch (Exception e) { e.printStackTrace(); } } /** * 校验文件路径和文件 * @param filePath */ private File validFile(String filePath){ if (StringUtils.isEmpty(filePath)) { throw new RuntimeException("输入的文件路径为空!"); } File file = new File(filePath); if (!file.exists()) { throw new RuntimeException("文件不存在!"); } else if (file.isDirectory()) { try { throw new RuntimeException(file.getCanonicalPath() + "这是一个目录!"); } catch (IOException e) { throw new RuntimeException(e); } } return file; } /** * 1.构建鉴权 * @return */ public VodClient createVodClient(){ ICredential auth = new BasicCredentials() .withAk(AK) .withSk(SK) ; return VodClient.newBuilder() .withCredential(auth) .withRegion(VodRegion.valueOf(REGION_NORTH4)) .build(); } /** * 2.创建媒资 * @param client * @param reqbody * @return */ public CreateAssetByFileUploadResponse createAssetByFileUpload(VodClient client, CreateAssetByFileUploadReq reqbody){ System.out.println("createAssetByFileUpload start"); CreateAssetByFileUploadRequest request = new CreateAssetByFileUploadRequest(); // 设置 X-Sdk-Date参数,ak/sk认证必传 request.setXSdkDate(getXSdkDate()); // 设置上传参数 request.withBody(reqbody); // 调用创建媒资 CreateAssetByFileUploadResponse response = client.createAssetByFileUpload(request); System.out.println("createAssetByFileUpload end; createAssetResponse:" + response.toString()); return response; } /** * 构建创建媒资请求参数 * @param fileName * @param videoName * @param title * @return */ public CreateAssetByFileUploadReq buildFileUploadReq(String fileName, String videoType, String videoName, String title){ CreateAssetByFileUploadReq req = new CreateAssetByFileUploadReq(); req.withVideoName(StringUtils.isNotEmpty(videoName) ? videoName : fileName); req.withTitle(StringUtils.isNotEmpty(title) ? title : fileName); // 设置媒资类型 req.withVideoType(videoType); return req; } /** * 取 X-Sdk-Date 参数,当前UTC时间, 时间格式 yyyyHHddTHHmmssZ 例如: 20240312T092514Z * @return */ public String getXSdkDate(){ TimeZone zone = TimeZone.getTimeZone("UTC"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'"); return LocalDateTime.now(zone.toZoneId()).format(formatter); } /** * 3.获取初始化上传任务授权 * @param client * @param assetResponse */ public ShowAssetTempAuthorityResponse initPartUploadAuthority(VodClient client, CreateAssetByFileUploadResponse assetResponse, String fileContentType){ System.out.println("获取初始化上传任务授权 initPartUploadAuthority start"); ShowAssetTempAuthorityRequest request = new ShowAssetTempAuthorityRequest(); request.setXSdkDate(getXSdkDate()); // 设置参数 request.withHttpVerb("POST"); request.withBucket(assetResponse.getTarget().getBucket()); request.withObjectKey(assetResponse.getTarget().getObject()); request.withContentType(fileContentType); // 发送初始化请求 ShowAssetTempAuthorityResponse response = client.showAssetTempAuthority(request); System.out.println("获取初始化上传任务授权 initPartUploadAuthority end; response: " + response.toString()); return response; } /** * 4.初始化分段上传 * @param signStr * @param contentType * @return */ public String initPartUpload(String signStr, String contentType) throws DocumentException { System.out.println("初始化分段上传 initPartUpload start"); HttpResponse response = HttpRequest.post(signStr).header("Content-type",contentType).execute(); System.out.println(response.body()); Document document = DocumentHelper.parseText(response.body()); Element root = document.getRootElement(); Element u = root.element("UploadId"); System.out.println("初始化分段上传 initPartUpload end; UploadId:" + u.getText()); return u.getText(); } /** * 5.获取分段上传授权 * @param client * @param fileContentType * @param assetResponse * @param contentMd5 * @param uploadId * @param partNumber * @return */ public ShowAssetTempAuthorityResponse getPartUploadAuthority(VodClient client, String fileContentType, CreateAssetByFileUploadResponse assetResponse, String contentMd5, String uploadId, int partNumber) { System.out.println("获取分段上传授权 getPartUploadAuthority start; partNumber: " + partNumber); ShowAssetTempAuthorityRequest request = new ShowAssetTempAuthorityRequest(); request.setXSdkDate(getXSdkDate()); request.withHttpVerb("PUT"); request.withBucket(assetResponse.getTarget().getBucket()); request.withObjectKey(assetResponse.getTarget().getObject()); request.withContentType(fileContentType); request.withContentMd5(contentMd5); request.withUploadId(uploadId); request.withPartNumber(partNumber); ShowAssetTempAuthorityResponse response = client.showAssetTempAuthority(request); System.out.println("获取分段上传授权 getPartUploadAuthority end; partNumber: " + partNumber + "; response" + response.toString()); return response; } /** * 6.上传分段 * @param signStr * @param fileByte * @param contentMd5 */ public void uploadPartFile(String signStr, byte[] fileByte, String contentMd5) { System.out.println("上传分段 uploadPartFile start"); HttpResponse response = HttpRequest.put(signStr) // 此处contentMd5不需要转义 .header("Content-MD5", contentMd5) .header("Content-Type", "application/octet-stream") .body(fileByte).execute(); System.out.println(response.toString()); if (response.getStatus() != 200) { throw new RuntimeException("上传分段 uploadPartFile end; 上传失败!"); } System.out.println("上传分段 uploadPartFile end"); } /** * 8.获取列举已上传段的授权 * @param client * @param assetResponse * @param uploadId * @return */ public ShowAssetTempAuthorityResponse listUploadedPartAuthority(VodClient client, CreateAssetByFileUploadResponse assetResponse, String uploadId){ System.out.println("获取列举已上传段的授权 listUploadedPartAuthority start"); ShowAssetTempAuthorityRequest request = new ShowAssetTempAuthorityRequest(); request.setXSdkDate(getXSdkDate()); request.withHttpVerb("GET"); request.withBucket(assetResponse.getTarget().getBucket()); request.withObjectKey(assetResponse.getTarget().getObject()); request.withUploadId(uploadId); ShowAssetTempAuthorityResponse response = client.showAssetTempAuthority(request); System.out.println("获取列举已上传段的授权 listUploadedPartAuthority end; response: " + response.toString()); return response; } /** * 9.查询已上传的分段 * @param signStr * @return */ public String listUploadedPart(String signStr) throws DocumentException { System.out.println("查询已上传的分段 listUploadedPart start"); int partNumberMarker = 0; Element mergerRoot = DocumentHelper.createElement("CompleteMultipartUpload"); while(true) { //列举分段 HttpResponse response = HttpRequest.get(signStr + "&part-number-marker=" + partNumberMarker).execute(); System.out.println("listUploadedPartResponse:" + response.body()); Document responseDocument = DocumentHelper.parseText(response.body()); Element rootResponse = responseDocument.getRootElement(); List<Element> elementsResponse = rootResponse.elements("Part"); Element partNumberMarkerElement = rootResponse.element("NextPartNumberMarker"); for (Element e : elementsResponse) { Element te = DocumentHelper.createElement("Part"); te.add(e.element("PartNumber").createCopy()); te.add(e.element("ETag").createCopy()); mergerRoot.add(te); } partNumberMarker = Integer.valueOf(partNumberMarkerElement.getText()); if(partNumberMarker % 1000 != 0) { break; } } System.out.println(mergerRoot.asXML()); System.out.println("查询已上传的分段 listUploadedPart end"); return mergerRoot.asXML(); } /** * 10.获取合并段授权 * @param client * @param assetResponse * @param uploadId * @return */ public ShowAssetTempAuthorityResponse mergeUploadedPartAuthority(VodClient client, CreateAssetByFileUploadResponse assetResponse, String uploadId) { System.out.println("获取合并段授权 mergeUploadedPartAuthority start"); ShowAssetTempAuthorityRequest request = new ShowAssetTempAuthorityRequest(); request.setXSdkDate(getXSdkDate()); request.withHttpVerb("POST"); request.withBucket(assetResponse.getTarget().getBucket()); request.withObjectKey(assetResponse.getTarget().getObject()); request.withUploadId(uploadId); ShowAssetTempAuthorityResponse response = client.showAssetTempAuthority(request); System.out.println("获取合并段授权 mergeUploadedPartAuthority end; response: " + response.toString()); return response; } /** * 11.合并分段 */ public void mergeUploadedPart(String signStr, String partInfo) { System.out.println("合并分段 mergeUploadedPart start"); // 请求消息头中增加“Content-Type”,值设置为“application/xml”。 HttpResponse response = HttpRequest.post(signStr) .header("Content-Type","application/xml") .body(partInfo) .execute(); System.out.println(response.toString()); if (response.getStatus() != 200) { throw new RuntimeException("合并分段 mergeUploadedPart end; 合并段失败!"); } System.out.println("合并分段 mergeUploadedPart end"); } /** * 12.确认上传完成 */ public void confirmUploaded(VodClient client, CreateAssetByFileUploadResponse assetResponse) { System.out.println("确认上传完成 confirmUploaded start"); ConfirmAssetUploadRequest request = new ConfirmAssetUploadRequest(); request.setXSdkDate(getXSdkDate()); ConfirmAssetUploadReq body = new ConfirmAssetUploadReq(); body.withStatus(ConfirmAssetUploadReq.StatusEnum.fromValue("CREATED")); body.withAssetId(assetResponse.getAssetId()); request.withBody(body); ConfirmAssetUploadResponse response = client.confirmAssetUpload(request); System.out.println("上传完成,assetId:" + response.toString()); } }
父主题: 分段上传代码示例