Updated on 2026-01-09 GMT+08:00
JavaScript
Multipart upload can be completed using different languages.
The following is the sample code in 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 authentication
var token = "";
var projectId = "";
const region = "cn-north-4";
var urlList;
function initUrl(projectId) {
let url = {
// API for creating a media asset.
createAssetUrl: "https://vod." + region + ".myhuaweicloud.com/v1.0/" + projectId + "/asset",
// API for obtaining authorization.
initAuthUrl: "https://vod." + region + ".myhuaweicloud.com/v1.0/" + projectId + "/asset/authority",
// API for confirming media asset upload.
confirmUploadedUrl: "https://vod." + region + ".myhuaweicloud.com/v1.0/" + projectId + "/asset/status/uploaded"
}
return url;
}
// The file part size is 1 MB (adjustable).
const bufferSize = 1024 * 1024;
// Start the upload.
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];
// An MP4 file is used as an example. For details about other formats, see the official website.
let fileType = "MP4";
let fileContentType = "video/mp4";
// 1. Set the request header. Token authentication is used as an example.
let headers = {
"X-Auth-Token": token,
"Content-Type": "application/json"
}
// 2. Create a VOD media asset.
let assetRsp = createAsset(file.name, file.name, fileType, headers);
// 3. Obtain authorization for initializing an upload task.
let initAuthResponse = getInitAuth(assetRsp, fileContentType, headers);
// 4. Initialize the multipart upload task.
let uploadId = initPartUpload(initAuthResponse, assetRsp, fileContentType);
// 5. Count the number of file parts.
let partNumber = 1;
// 6. Specify the location where file data is read.
let position = 0;
let blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice;
// 7. Repeat steps 5 to 6 to upload parts.
readAndUpload(file, blobSlice, position, partNumber, assetRsp, fileContentType, uploadId, headers,
function (assetRsp, uploadId, headers) {
// 8. Obtain authorization for listing uploaded parts.
let listAuthResp = listUploadedPartAuthority(assetRsp, uploadId, headers);
// 9. List uploaded parts.
let partInfo = listUploadedPart(listAuthResp.sign_str, assetRsp, uploadId);
// 10. Obtain authorization for merging parts.
let mergeAuthResp = mergeUploadedPartAuthority(assetRsp, uploadId, headers);
// 11. Merge parts.
mergeUploadedPart(mergeAuthResp.sign_str, partInfo, assetRsp, uploadId);
// 12. Confirm the upload.
confirmUploaded(assetRsp.asset_id, headers);
alert("Uploaded;assetId:" + assetRsp.asset_id);
}
);
}
// 2. Create a VOD media asset.
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. Obtain authorization for initializing an upload task.
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. Initialize the multipart upload task. An upload ID will be returned.
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. Obtain authorization for multipart upload.
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),// There are special characters, which should be escaped.
"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. Upload parts.
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. Repeat steps 5 to 6 to upload parts.
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);
// Calculate the MD5 value of a file part.
const md5 = spark.end()
// Encode the MD5 byte array using Base64.
const bytes = new Uint8Array(md5.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
const base64 = btoa(String.fromCharCode.apply(null, bytes));
// 5. Obtain authorization for multipart upload.
let uploadAuth = getPartUploadAuthority(assetRsp, fileContentType, uploadId, content_md5, partNum, headers);
// 6. Upload parts.
uploadPartFile(uploadAuth, assetRsp, content_md5, partNum, uploadId, e.target.result);
partNum++;
// Check whether the data read is complete. If not, continue the upload.
if (position + bufferSize < file.size) {
readAndUpload(file, blobSlice, position + bufferSize, partNum, assetRsp, fileContentType, uploadId, headers, afterUpload);
} else {
// After the upload is complete, perform the subsequent steps.
afterUpload(assetRsp, uploadId, headers);
}
}
fileReader.readAsArrayBuffer(blobSlice.call(file, position, position + bufferSize));
}
// 8. Obtain authorization for listing uploaded parts.
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. Query uploaded parts.
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");
// Construct parameters for merging parts.
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. Obtain authorization for merging parts.
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. Merge parts.
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. Confirm the upload.
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);
}
// Send a request and wait for result return. Change the content based on the actual framework.
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()">Upload</button>
</body>
</html>
Parent topic: Sample Code for Multipart Upload
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
The system is busy. Please try again later.
For any further questions, feel free to contact us through the chatbot.
Chatbot