Object Storage Service (OSS) provides a multipart upload feature that lets you split a large object into multiple parts. After these parts are uploaded, you can call the CompleteMultipartUpload operation to combine them into a complete object.
Usage notes
For more information about OSS-supported regions and endpoints, see Regions and endpoints.
To perform a multipart upload, you must have the
oss:PutObjectpermission. For more information, see Grant permissions to a RAM user using a custom policy.
Multipart upload process
A multipart upload consists of the following three steps:
Initiate the multipart upload.
You can call the client.initiateMultipartUpload method. OSS returns a globally unique upload ID.
Upload parts.
You can call the client.uploadPart method to upload the parts.
NoteFor a specific upload ID, the part number identifies the relative position of a part in the complete object. If you upload a new part with an existing part number, the existing part is overwritten.
OSS returns the MD5 hash of the received part in the ETag header.
OSS calculates the MD5 hash of the uploaded data and compares it with the MD5 hash calculated by the SDK. If the two hashes do not match, OSS returns the `InvalidDigest` error code.
Complete the multipart upload.
After all parts are uploaded, you can call the client.completeMultipartUpload method to combine the parts into a complete object.
Sample code
The following code shows how to split a large local file into multiple parts, upload the parts to a bucket concurrently, and then combine the parts into a complete object.
import Client, { FilePath, RequestError, THarmonyEmptyBodyApiRes } from '@aliyun/oss';
import { fileIo as fs } from '@kit.CoreFileKit';
// Create an OSS client instance.
const client = new Client({
// Replace with the AccessKey ID from your STS temporary access credential.
accessKeyId: 'yourAccessKeyId',
// Replace with the AccessKey secret from your STS temporary access credential.
accessKeySecret: 'yourAccessKeySecret',
// Replace with the security token from your STS temporary access credential.
securityToken: 'yourSecurityToken',
// Specify the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the region to oss-cn-hangzhou.
region: 'oss-cn-hangzhou',
});
// Specify the name of the bucket to use. Replace with your actual bucket name.
const bucket = 'yourBucketName';
// Specify the name of the object (file) to upload. Replace with your actual object name.
const key = 'yourObjectName';
/**
* Upload a file to OSS using multipart upload.
* Use multipart upload to split a large file into multiple parts and upload them to a specified bucket and key.
*/
const multipartUpload = async () => {
try {
// Initiate the multipart upload task and get the uploadId.
const initRes = await client.initiateMultipartUpload({
bucket, // Bucket name
key, // Object (file) name
});
// Get the uploadId from the initialization response. It is used for subsequent part uploads and to complete the upload.
const uploadId = initRes.data.uploadId;
// Specify the local file path.
const filePath = new FilePath('yourFilePath');// Replace with the actual local file path.
// Get the file metadata, such as the file size.
const fileStat = await fs.stat(filePath.filePath);
// Define the size of each part (10 MB).
const chunkSize = 1024 * 1024 * 10;
// Calculate the total number of parts.
let totalParts = Math.ceil(fileStat.size / chunkSize);
// Current part number.
let partNumber = 1;
// Store the Promise objects for all part uploads.
const waitList: Promise<THarmonyEmptyBodyApiRes>[] = [];
// Loop to process each part.
while (partNumber <= totalParts) {
// Calculate the start position of the current part.
const offset = (partNumber - 1) * chunkSize;
// Call the uploadPart method to upload the current part.
const uploadPromise = client.uploadPart({
bucket, // Bucket name
key, // Object (file) name
uploadId, // The uploadId returned from initialization.
partNumber, // Current part number.
data: filePath, // File path.
length: Math.min(chunkSize, fileStat.size - offset), // Size of the current part.
offset, // Start offset of the current part.
});
// Add the part upload Promise to the wait list.
waitList.push(uploadPromise);
// Increment the part number.
partNumber++;
}
// Wait for all part uploads to complete.
const uploadResList = await Promise.all(waitList);
// After all parts are uploaded, call completeMultipartUpload to complete the upload task.
const completeRes = await client.completeMultipartUpload({
bucket, // Bucket name
key, // Object (file) name
uploadId, // The uploadId returned from initialization.
completeAll: true, // Automatically complete all parts.
});
// Print the result of the completed multipart upload.
console.log(JSON.stringify(completeRes));
} catch (err) {
// Catch exceptions that occur during the request.
if (err instanceof RequestError) {
// If a known type of error occurs, print the error code, error message, request ID, status code, EC code, and other information.
console.log('code: ', err.code); // Error code.
console.log('message: ', err.message); // Error message.
console.log('requestId: ', err.requestId); // Request ID.
console.log('status: ', err.status); // HTTP status code.
console.log('ec: ', err.ec); // Error code.
} else {
// Print other unknown types of errors.
console.log('unknown error: ', err);
}
}
};
// Call the multipartUpload function to perform the multipart upload operation.
multipartUpload();