更新时间:2025-12-08 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);
// 5.文件分段计数
let partNumber = 1;
// 6.文件读取位置
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>
父主题: 分段上传代码示例