OSS提供的分區上傳(Multipart Upload)功能,將要上傳的較大檔案(Object)分成多個分區(Part)來分別上傳,上傳完成後再調用CompleteMultipartUpload介面將這些Part組合成一個Object。
注意事項
關於OSS支援的Region與Endpoint的對應關係,請參見地區和Endpoint。
要分區上傳,您必須有
oss:PutObject許可權。具體操作,請參見為RAM使用者授予自訂的權限原則。
分區上傳流程
分區上傳(Multipart Upload)分為以下三個步驟:
初始化一個分區上傳事件。
調用client.initiateMultipartUpload方法返回OSS建立的全域唯一的uploadID。
上傳分區。
調用client.uploadPart方法上傳分區資料。
說明對於同一個uploadID,分區號(partNumber)標識了該分區在整個檔案內的相對位置。如果使用同一個分區號上傳了新的資料,那麼OSS上該分區已有的資料將會被覆蓋。
OSS將收到的分區資料的MD5值放在ETag頭內返回給使用者。
OSS計算上傳資料的MD5值,並與SDK計算的MD5值比較,如果不一致則返回InvalidDigest錯誤碼。
完成分區上傳。
所有分區上傳完成後,調用client.completeMultipartUpload方法將所有分區合并成完整的檔案。
範例程式碼
以下代碼展示如何將本地的大檔案分割成多個分區檔案並發上傳到儲存空間,然後合并成完整的檔案對象。
import Client, { FilePath, RequestError, THarmonyEmptyBodyApiRes } from '@aliyun/oss';
import { fileIo as fs } from '@kit.CoreFileKit';
// 建立OSS用戶端執行個體
const client = new Client({
// 請替換為STS臨時訪問憑證的Access Key ID
accessKeyId: 'yourAccessKeyId',
// 請替換為STS臨時訪問憑證的Access Key Secret
accessKeySecret: 'yourAccessKeySecret',
// 請替換為STS臨時訪問憑證的Security Token
securityToken: 'yourSecurityToken',
// 填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為oss-cn-hangzhou
region: 'oss-cn-hangzhou',
});
// 指定要操作的Bucket名稱,請替換為您實際使用的Bucket名稱
const bucket = 'yourBucketName';
// 指定要上傳的對象(檔案)名稱,請替換為您實際要上傳的對象名稱
const key = 'yourObjectName';
/**
* 分區上傳檔案到OSS。
* 使用分區上傳(Multipart Upload)將大檔案分成多個部分上傳到指定的Bucket和Key。
*/
const multipartUpload = async () => {
try {
// 初始化分區上傳任務,擷取uploadId
const initRes = await client.initiateMultipartUpload({
bucket, // Bucket名稱
key, // 對象(檔案)名稱
});
// 擷取初始化返回的uploadId,用於後續分區上傳和完成上傳
const uploadId = initRes.data.uploadId;
// 指定本地檔案路徑
const filePath = new FilePath('yourFilePath');// 請替換為實際的本地檔案路徑
// 擷取檔案的元資訊(如檔案大小)
const fileStat = await fs.stat(filePath.filePath);
// 定義每個分區的大小(10MB)
const chunkSize = 1024 * 1024 * 10;
// 計算總分區數
let totalParts = Math.ceil(fileStat.size / chunkSize);
// 當前分區編號
let partNumber = 1;
// 儲存所有分區上傳的Promise對象
const waitList: Promise<THarmonyEmptyBodyApiRes>[] = [];
// 迴圈處理每個分區
while (partNumber <= totalParts) {
// 計算當前分區的起始位置
const offset = (partNumber - 1) * chunkSize;
// 調用uploadPart方法上傳當前分區
const uploadPromise = client.uploadPart({
bucket, // Bucket名稱
key, // 對象(檔案)名稱
uploadId, // 初始化返回的uploadId
partNumber, // 當前分區編號
data: filePath, // 檔案路徑
length: Math.min(chunkSize, fileStat.size - offset), // 當前分區的大小
offset, // 當前分區的起始位移量
});
// 將分區上傳的Promise添加到等待列表
waitList.push(uploadPromise);
// 增加分區編號
partNumber++;
}
// 等待所有分區上傳完成
const uploadResList = await Promise.all(waitList);
// 當所有分區上傳完成後,調用completeMultipartUpload完成上傳任務
const completeRes = await client.completeMultipartUpload({
bucket, // Bucket名稱
key, // 對象(檔案)名稱
uploadId, // 初始化返回的uploadId
completeAll: true, // 自動完成所有分區
});
// 列印完成分區上傳的結果
console.log(JSON.stringify(completeRes));
} catch (err) {
// 捕獲請求過程中的異常資訊
if (err instanceof RequestError) {
// 如果是已知類型的錯誤,則列印錯誤碼、錯誤訊息、請求ID、狀態代碼、EC碼等資訊
console.log('code: ', err.code); // 錯誤碼
console.log('message: ', err.message); // 錯誤訊息
console.log('requestId: ', err.requestId); // 請求ID
console.log('status: ', err.status); // HTTP狀態代碼
console.log('ec: ', err.ec); // 錯誤碼
} else {
// 列印其他未知類型的錯誤
console.log('unknown error: ', err);
}
}
};
// 調用multipartUpload函數執行分區上傳操作
multipartUpload();