更新时间:2025-09-09 GMT+08:00
JavaScript
分段上传JavaScript语言的示例代码,如下所示:
<!DOCTYPE html> <html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/spark-md5/3.0.2/spark-md5.min.js"></script> <script> // token认证 var token = ""; var projectId = ""; const region = "cn-north-4"; var urlList; function initUrl(projectId) { let url = { // 创建媒资接口 createAssetUrl: "https://vod." + region + ".myhuaweicloud.com/v1.0/" + projectId + "/asset", // 获取授权接口 initAuthUrl: "https://vod." + region + ".myhuaweicloud.com/v1.0/" + projectId + "/asset/authority", // 确认媒资上传接口 confirmUploadedUrl: "https://vod." + region + ".myhuaweicloud.com/v1.0/" + projectId + "/asset/status/uploaded" } return url; } // 文件分段大小1Mb,根据用户实际情况自行调整 const bufferSize = 1024 * 1024; // 开始上传 function startUpload() { token = document.getElementById("token").value; projectId = document.getElementById("projectId").value; urlList = initUrl(projectId); let files = document.getElementById("file").files; let file = files[0]; // 此处仅以MP4文件示例,其他格式可参考官网说明 let fileType = "MP4"; let fileContentType = "video/mp4"; // 1. 以token鉴权为例,设置请求头 let headers = { "X-Auth-Token": token, "Content-Type": "application/json" } // 2.创建点播媒资 let assetRsp = createAsset(file.name, file.name, fileType, headers); // 3.获取初始化上传任务授权 let initAuthResponse = getInitAuth(assetRsp, fileContentType, headers); // 4.初始化分段上传任务 let uploadId = initPartUpload(initAuthResponse, assetRsp, fileContentType); // 文件分段计数 let partNumber = 1; // 文件读取位置 let position = 0; let blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice; // 7.循环5-6上传分段 readAndUpload(file, blobSlice, position, partNumber, assetRsp, fileContentType, uploadId, headers, function (assetRsp, uploadId, headers) { // 8.获取列举已上传段授权 let listAuthResp = listUploadedPartAuthority(assetRsp, uploadId, headers); // 9.列举已上传段 let partInfo = listUploadedPart(listAuthResp.sign_str, assetRsp, uploadId); // 10.获取合并段授权 let mergeAuthResp = mergeUploadedPartAuthority(assetRsp, uploadId, headers); // 11.合并段 mergeUploadedPart(mergeAuthResp.sign_str, partInfo, assetRsp, uploadId); // 12.确认上传 confirmUploaded(assetRsp.asset_id, headers); alert("上传结束;assetId:" + assetRsp.asset_id); } ); } // 2. 创建点播媒资 function createAsset(title, videoName, videoType, headers) { let body = { "title": title, "video_name": videoName, "video_type": videoType } let resp = sendRequest("POST", urlList.createAssetUrl, JSON.stringify(body), headers); return JSON.parse(resp); } // 3.获取上传初始化任务授权 function getInitAuth(assetRsp, fileContentType, headers) { let params = { "http_verb": "POST", "content_type": fileContentType, "bucket": assetRsp.target.bucket, "object_key": assetRsp.target.object } let temp = "?"; for (let e in params) { temp += e + "=" + params[e] + "&"; } let resp = sendRequest("GET", urlList.initAuthUrl + temp, null, headers); return JSON.parse(resp); } // 4.初始化分段上传, 返回uploadId function initPartUpload(signStr, assetRsp, contentType) { let initUrl = "https://" + assetRsp.target.bucket + ".obs." + region + ".myhuaweicloud.com/" + assetRsp.target.object + "?uploads&" + signStr.sign_str; let resp = sendRequest("POST", initUrl, null, { "Content-Type": contentType }); let domParser = new DOMParser(); let dom = domParser.parseFromString(resp, "text/xml"); return dom.getElementsByTagName("UploadId")[0].firstChild.nodeValue; } // 5.获取分段上传授权 function getPartUploadAuthority(assetRsp, fileContentType, uploadId, contentMd5, partNumber, headers) { let params = { "http_verb": "PUT", "content_type": fileContentType, "bucket": assetRsp.target.bucket, "object_key": assetRsp.target.object, "content_md5": encodeURIComponent(contentMd5),// 有特殊符号,此处加转义 "upload_id": uploadId, "part_number": partNumber } let temp = "?"; for (let e in params) { temp += e + "=" + params[e] + "&"; } let resp = sendRequest("GET", urlList.initAuthUrl + temp, null, headers); return JSON.parse(resp); } // 6.上传分段 function uploadPartFile(uploadAuth, assetRsp, contentMd5, partNumber, uploadId, content) { let url = "https://" + assetRsp.target.bucket + ".obs." + region + ".myhuaweicloud.com/" + assetRsp.target.object + "?partNumber=" + partNumber + "&uploadId=" + uploadId + "&" + uploadAuth.sign_str; let headers = { "Content-Type": "application/octet-stream", "Content-MD5": contentMd5 } let resp = sendRequest("PUT", url, content, headers); } // 7.循环5-6上传分段 function readAndUpload(file, blobSlice, position, partNum, assetRsp, fileContentType, uploadId, headers, afterUpload) { let fileReader = new FileReader(); const spark = new SparkMD5.ArrayBuffer(); fileReader.onload = function (e) { spark.append(e.target.result); // 先计算文件分段md5 const md5 = spark.end() // base64 encode md5字节数组 const bytes = new Uint8Array(md5.match(/.{1,2}/g).map(byte => parseInt(byte, 16))); const base64 = btoa(String.fromCharCode.apply(null, bytes)); // 5.获取分段上传授权 let uploadAuth = getPartUploadAuthority(assetRsp, fileContentType, uploadId, content_md5, partNum, headers); // 6.上传分段 uploadPartFile(uploadAuth, assetRsp, content_md5, partNum, uploadId, e.target.result); partNum++; // 判断是否读完,未读完继续上传 if (position + bufferSize < file.size) { readAndUpload(file, blobSlice, position + bufferSize, partNum, assetRsp, fileContentType, uploadId, headers, afterUpload); } else { // 全部上传完成后执行后续步骤 afterUpload(assetRsp, uploadId, headers); } } fileReader.readAsArrayBuffer(blobSlice.call(file, position, position + bufferSize)); } // 8.获取列举分段上传授权 function listUploadedPartAuthority(assetRsp, uploadId, headers) { let params = { "http_verb": "GET", "bucket": assetRsp.target.bucket, "object_key": assetRsp.target.object, "upload_id": uploadId } let temp = "?"; for (let e in params) { temp += e + "=" + params[e] + "&"; } let resp = sendRequest("GET", urlList.initAuthUrl + temp, null, headers); return JSON.parse(resp); } // 9.查询已上传的分段 function listUploadedPart(signStr, assetRsp, uploadId) { let url = "https://" + assetRsp.target.bucket + ".obs." + region + ".myhuaweicloud.com/" + assetRsp.target.object + "?" + signStr + "&uploadId=" + uploadId; let nextPartNumberMarker = 0; let result = "<CompleteMultipartUpload>"; let domParser = new DOMParser(); while (true) { let resp = sendRequest("GET", url + "&part-number-marker=" + nextPartNumberMarker, null, {}); let dom = domParser.parseFromString(resp, "text/xml"); let part = dom.getElementsByTagName("Part"); // 构建合并段的参数 for (let i = 0; i < part.length; i++) { let ele = part[i]; let num = ele.getElementsByTagName("PartNumber")[0].firstChild.nodeValue; let tag = ele.getElementsByTagName("ETag")[0].firstChild.nodeValue; result += "<Part>" + "<PartNumber>" + num + "</PartNumber>" + "<ETag>" + tag + "</ETag>" + "</Part>" ; } nextPartNumberMarker = Number(dom.getElementsByTagName("NextPartNumberMarker")[0].firstChild.nodeValue); if (nextPartNumberMarker % 1000 != 0) { break; } } result += "</CompleteMultipartUpload>"; return result; } // 10.获取合并段授权 function mergeUploadedPartAuthority(assetRsp, uploadId, headers) { let params = { "http_verb": "POST", "bucket": assetRsp.target.bucket, "object_key": assetRsp.target.object, "upload_id": uploadId } let temp = "?"; for (let e in params) { temp += e + "=" + params[e] + "&"; } let resp = sendRequest("GET", urlList.initAuthUrl + temp, null, headers); return JSON.parse(resp); } // 11.合并段 function mergeUploadedPart(signStr, partInfo, assetRsp, uploadId) { let url = "https://" + assetRsp.target.bucket + ".obs." + region + ".myhuaweicloud.com/" + assetRsp.target.object + "?" + signStr + "&uploadId=" + uploadId; let resp = sendRequest("POST", url, partInfo, { "Content-Type": "application/xml" }); } // 12.确认上传 function confirmUploaded(assetId, headers) { let body = { "asset_id": assetId, "status": "CREATED" }; let resp = sendRequest("POST", urlList.confirmUploadedUrl, JSON.stringify(body), headers); return console.log(resp); } // 发送请求并返回结果,可以实际框架情况进行替换 function sendRequest(method, url, data, headers) { var xhr = new XMLHttpRequest(); xhr.open(method, url, false); for (let i in headers) { xhr.setRequestHeader(i, headers[i]); } xhr.send(data); return xhr.responseText; } </script> </head> <body> <p>projectId: <input type="input" id="projectId"></input></p> <p>token: <input type="input" id="token"></input></p> <p><input type="file" id="file"></input></p> <button onclick="startUpload()">上传</button> </body> </html>
父主题: 分段上传代码示例