Gunakan unggah multi-bagian untuk mengunggah file besar ke OSS secara andal. Alih-alih mengirim seluruh file dalam satu permintaan, Anda membagi file tersebut menjadi beberapa bagian, mengunggahnya secara paralel, lalu menggabungkannya menjadi satu objek utuh. Pendekatan ini meningkatkan throughput, memulihkan diri dengan cepat dari gangguan jaringan, dan memungkinkan Anda melanjutkan unggahan yang terputus tanpa memulai dari awal.
Prasyarat
Sebelum memulai, pastikan Anda telah memiliki:
Bucket OSS di wilayah tempat Anda ingin menyimpan objek. Lihat Wilayah dan titik akhir
Izin
oss:PutObjectpada bucket tersebut. Lihat Berikan izin kepada RAM user menggunakan kebijakan kustomKredensial akses temporary STS yang valid (ID AccessKey, Rahasia AccessKey, dan token keamanan)
Cara kerja
Unggah multi-bagian mengikuti tiga langkah:
Initiate — Panggil
client.initiateMultipartUpload. OSS mengembalikan ID unggah unik secara global yang mengidentifikasi sesi unggah ini.Unggah bagian — Panggil
client.uploadPartuntuk setiap bagian, diidentifikasi berdasarkan nomor bagian. Bagian-bagian tersebut dapat diunggah secara paralel.Complete — Panggil
client.completeMultipartUpload. OSS merangkai bagian-bagian tersebut berdasarkan urutan nomor bagian menjadi satu objek utuh.
Perilaku penomoran bagian:
Nomor bagian menentukan posisi masing-masing bagian dalam objek akhir.
Mengunggah bagian baru dengan nomor bagian yang sudah ada akan menimpa bagian sebelumnya.
OSS mengembalikan hash MD5 dari setiap bagian yang diterima dalam header
ETag.Jika hash MD5 dari data yang diunggah tidak sesuai dengan hash yang dihitung oleh SDK, OSS mengembalikan error
InvalidDigest.
Unggah file dalam beberapa bagian
Contoh berikut membagi file lokal menjadi bagian-bagian berukuran 10 MB dan mengunggahnya secara konkuren menggunakan Promise.all.
import Client, { FilePath, RequestError, THarmonyEmptyBodyApiRes } from '@aliyun/oss';
import { fileIo as fs } from '@kit.CoreFileKit';
// Buat instans klien OSS.
const client = new Client({
// Ganti dengan ID AccessKey dari kredensial akses temporary STS Anda.
accessKeyId: 'yourAccessKeyId',
// Ganti dengan Rahasia AccessKey dari kredensial akses temporary STS Anda.
accessKeySecret: 'yourAccessKeySecret',
// Ganti dengan token keamanan dari kredensial akses temporary STS Anda.
securityToken: 'yourSecurityToken',
// Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di
// wilayah China (Hangzhou), atur region menjadi oss-cn-hangzhou.
region: 'oss-cn-hangzhou',
});
const bucket = 'yourBucketName'; // Ganti dengan nama bucket aktual Anda.
const key = 'yourObjectName'; // Ganti dengan nama objek aktual Anda.
const multipartUpload = async () => {
try {
// Langkah 1: Mulai unggah multi-bagian dan dapatkan ID unggah.
const initRes = await client.initiateMultipartUpload({ bucket, key });
const uploadId = initRes.data.uploadId;
// Langkah 2: Bagi file menjadi beberapa bagian dan unggah secara konkuren.
const filePath = new FilePath('yourFilePath'); // Ganti dengan path file lokal aktual.
const fileStat = await fs.stat(filePath.filePath);
const chunkSize = 1024 * 1024 * 10; // 10 MB per bagian.
const totalParts = Math.ceil(fileStat.size / chunkSize);
const waitList: Promise<THarmonyEmptyBodyApiRes>[] = [];
for (let partNumber = 1; partNumber <= totalParts; partNumber++) {
const offset = (partNumber - 1) * chunkSize;
const uploadPromise = client.uploadPart({
bucket,
key,
uploadId,
partNumber,
data: filePath,
length: Math.min(chunkSize, fileStat.size - offset), // Ukuran bagian saat ini.
offset, // Offset awal bagian saat ini.
});
waitList.push(uploadPromise);
}
// Tunggu hingga semua bagian selesai diunggah.
await Promise.all(waitList);
// Langkah 3: Selesaikan unggah multi-bagian.
const completeRes = await client.completeMultipartUpload({
bucket,
key,
uploadId,
completeAll: true, // Secara otomatis merangkai semua bagian yang telah diunggah.
});
console.log(JSON.stringify(completeRes));
} catch (err) {
if (err instanceof RequestError) {
console.log('code: ', err.code);
console.log('message: ', err.message);
console.log('requestId: ', err.requestId);
console.log('status: ', err.status);
console.log('ec: ', err.ec);
} else {
console.log('unknown error: ', err);
}
}
};
multipartUpload();Parameter utama:
| Parameter | Deskripsi |
|---|---|
uploadId | Pengenal unik yang dikembalikan oleh initiateMultipartUpload. Berikan nilai ini ke semua panggilan uploadPart dan completeMultipartUpload berikutnya. |
partNumber | Nomor urut setiap bagian, dimulai dari 1. Menentukan posisi bagian dalam objek akhir. |
offset | Offset byte dalam file sumber tempat bagian ini dimulai. |
length | Ukuran bagian ini dalam byte. Bagian terakhir bisa lebih kecil dari chunkSize. |
completeAll | Jika diatur ke true, OSS secara otomatis merangkai semua bagian yang telah diunggah tanpa memerlukan daftar bagian eksplisit. |
Operasi tambahan
Batalkan unggah multi-bagian
Panggil client.abortMultipartUpload untuk membatalkan unggahan yang sedang berlangsung dan membebaskan penyimpanan yang digunakan oleh bagian-bagian yang telah diunggah.
import Client, { RequestError } from '@aliyun/oss';
const client = new Client({
accessKeyId: 'yourAccessKeyId',
accessKeySecret: 'yourAccessKeySecret',
securityToken: 'yourSecurityToken',
region: 'oss-cn-hangzhou',
});
const bucket = 'yourBucketName';
const key = 'yourObjectName';
const abortMultipartUpload = async () => {
try {
const res = await client.abortMultipartUpload({
bucket,
key,
// ID unggah yang dikembalikan oleh initiateMultipartUpload, atau diambil melalui listMultipartUploads.
uploadId: 'yourUploadId',
});
console.log(JSON.stringify(res));
} catch (err) {
if (err instanceof RequestError) {
console.log('code: ', err.code);
console.log('message: ', err.message);
console.log('requestId: ', err.requestId);
console.log('status: ', err.status);
console.log('ec: ', err.ec);
} else {
console.log('unknown error: ', err);
}
}
};
abortMultipartUpload();Daftar bagian yang telah diunggah
Panggil client.listParts untuk mengambil daftar bagian yang telah diunggah untuk ID unggah tertentu. Gunakan ini untuk memeriksa progres unggahan atau melanjutkan unggahan yang terputus.
import Client, { RequestError } from '@aliyun/oss';
const client = new Client({
accessKeyId: 'yourAccessKeyId',
accessKeySecret: 'yourAccessKeySecret',
securityToken: 'yourSecurityToken',
region: 'oss-cn-hangzhou',
});
const bucket = 'yourBucketName';
const key = 'yourObjectName';
const listParts = async () => {
try {
const res = await client.listParts({
bucket,
key,
// ID unggah yang dikembalikan oleh initiateMultipartUpload, atau diambil melalui listMultipartUploads.
uploadId: 'yourUploadId',
});
console.log(JSON.stringify(res));
} catch (err) {
if (err instanceof RequestError) {
console.log('code: ', err.code);
console.log('message: ', err.message);
console.log('requestId: ', err.requestId);
console.log('status: ', err.status);
console.log('ec: ', err.ec);
} else {
console.log('unknown error: ', err);
}
}
};
listParts();Daftar unggahan multi-bagian yang sedang berlangsung
Panggil client.listMultipartUploads untuk menampilkan semua unggahan di bucket yang telah dimulai tetapi belum diselesaikan atau dibatalkan. Ini berguna untuk audit unggahan yang belum lengkap serta mengidentifikasi ID unggah untuk dilanjutkan atau dibatalkan.
import Client, { RequestError } from '@aliyun/oss';
const client = new Client({
accessKeyId: 'yourAccessKeyId',
accessKeySecret: 'yourAccessKeySecret',
securityToken: 'yourSecurityToken',
region: 'oss-cn-hangzhou',
});
const bucket = 'yourBucketName';
const listMultipartUploads = async () => {
try {
const res = await client.listMultipartUploads({ bucket });
console.log(JSON.stringify(res));
} catch (err) {
if (err instanceof RequestError) {
console.log('code: ', err.code);
console.log('message: ', err.message);
console.log('requestId: ', err.requestId);
console.log('status: ', err.status);
console.log('ec: ', err.ec);
} else {
console.log('unknown error: ', err);
}
}
};
listMultipartUploads();Lanjutkan unggahan yang terputus
Di HarmonyOS, aplikasi mungkin ditangguhkan atau jaringan terputus di tengah proses unggah. Karena ID unggah dikembalikan saat inisiasi dan tetap tersimpan di OSS, Anda dapat melanjutkan unggahan tanpa mengunggah ulang bagian-bagian yang telah selesai:
Simpan
uploadIdyang dikembalikan olehinitiateMultipartUploadke penyimpanan persisten (misalnya, file lokal atau database).Jika unggahan terputus, panggil
client.listPartsdenganuploadIdyang telah disimpan untuk menentukan bagian mana saja yang telah diunggah.Unggah hanya bagian yang belum ada menggunakan
client.uploadPart.Panggil
client.completeMultipartUploadsetelah semua bagian tersedia.
Pola ini menghindari pemborosan bandwidth dan sangat penting saat menggunakan jaringan seluler.