OSS提供的分區上傳(Multipart Upload)功能,將要上傳的較大檔案(Object)分成多個分區(Part)來分別上傳,上傳完成後再調用CompleteMultipartUpload介面將這些Part組合成一個Object來達到斷點續傳的效果。
分區上傳流程
分區上傳(Multipart Upload)分為以下三個步驟:
初始化一個分區上傳事件。
調用$ossClient->initiateMultipartUpload方法返回OSS建立的全域唯一的uploadId。
上傳分區。
調用$ossClient->uploadPart方法上傳分區資料。
說明對於同一個uploadId,分區號(PartNumber)標識了該分區在整個檔案內的相對位置。如果使用同一個分區號上傳了新的資料,則OSS上該分區已有的資料將會被覆蓋。
OSS將收到的分區資料的MD5值放在ETag頭內返回給使用者。
OSS計算上傳資料的MD5值,並與SDK計算的MD5值比較,如果不一致則返回InvalidDigest錯誤碼。
完成分區上傳。
調用$ossClient->completeMultipartUpload方法將所有分區合并成完整的檔案。
分區上傳完整樣本
以下通過一個完整的樣本對分區上傳的流程進行逐步解析:
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
}
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\CoreOssException;
use OSS\Core\OssUtil;
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
$endpoint = 'https://oss-cn-hangzhou.aliyuncs.com';
// 填寫Bucket名稱,例如examplebucket。
$bucket= 'examplebucket';
//填寫不包含Bucket名稱在內的Object完整路徑,例如exampledir/exampleobject.txt。
$object = 'exampledir/exampleobject.txt';
// 填寫本地檔案的完整路徑。
$uploadFile = 'D:\\localpath\\examplefile.txt';
$initOptions = array(
OssClient::OSS_HEADERS => array(
// 指定該Object被下載時的網頁緩衝行為。
// 'Cache-Control' => 'no-cache',
// 指定該Object被下載時的名稱。
// 'Content-Disposition' => 'attachment;filename=oss_download.jpg',
// 指定該Object被下載時的內容編碼格式。
// 'Content-Encoding' => 'utf-8',
// 指定到期時間,單位為毫秒。
// 'Expires' => 150,
// 指定初始化分區上傳時是否覆蓋同名Object。此處設定為true,表示禁止覆蓋同名Object。
//'x-oss-forbid-overwrite' => 'true',
// 指定上傳該Object的每個part時使用的伺服器端加密方式。
// 'x-oss-server-side-encryption'=> 'KMS',
// 指定Object的密碼編譯演算法。
// 'x-oss-server-side-data-encryption'=>'SM4',
// 指定KMS託管的使用者主要金鑰。
//'x-oss-server-side-encryption-key-id' => '9468da86-3509-4f8d-a61e-6eab1eac****',
// 指定Object的儲存類型。
// 'x-oss-storage-class' => 'Standard',
// 指定Object的對象標籤,可同時設定多個標籤。
// 'x-oss-tagging' => 'TagA=A&TagB=B',
),
);
/**
* 步驟1:初始化一個分區上傳事件,並擷取uploadId。
*/
try{
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
"region"=> "cn-hangzhou"
);
$ossClient = new OssClient($config);
//返回uploadId。uploadId是分區上傳事件的唯一標識,您可以根據uploadId發起相關的操作,如取消分區上傳、查詢分區上傳等。
$uploadId = $ossClient->initiateMultipartUpload($bucket, $object, $initOptions);
print("initiateMultipartUpload OK" . "\n");
// 根據uploadId執行取消分區上傳事件或者列舉已上傳分區的操作。
// 如果您需要根據您需要uploadId執行取消分區上傳事件的操作,您需要在調用InitiateMultipartUpload完成初始化分區之後擷取uploadId。
// 如果您需要根據您需要uploadId執行列舉已上傳分區的操作,您需要在調用InitiateMultipartUpload完成初始化分區之後,且在調用CompleteMultipartUpload完成分區上傳之前擷取uploadId。
//print("UploadId: " . $uploadId . "\n");
} catch(OssException $e) {
printf($e->getMessage() . "\n");
return;
}
/*
* 步驟2:上傳分區。
*/
$partSize = 10 * 1024 * 1024;
$uploadFileSize = sprintf('%u',filesize($uploadFile));
$pieces = $ossClient->generateMultiuploadParts($uploadFileSize, $partSize);
$responseUploadPart = array();
$uploadPosition = 0;
$isCheckMd5 = true;
foreach ($pieces as $i => $piece) {
$fromPos = $uploadPosition + (integer)$piece[$ossClient::OSS_SEEK_TO];
$toPos = (integer)$piece[$ossClient::OSS_LENGTH] + $fromPos - 1;
$upOptions = array(
// 上傳檔案。
$ossClient::OSS_FILE_UPLOAD => $uploadFile,
// 設定分區號。
$ossClient::OSS_PART_NUM => ($i + 1),
// 指定分區上傳起始位置。
$ossClient::OSS_SEEK_TO => $fromPos,
// 指定檔案長度。
$ossClient::OSS_LENGTH => $toPos - $fromPos + 1,
// 是否開啟MD5校正,true為開啟。
$ossClient::OSS_CHECK_MD5 => $isCheckMd5,
);
// 開啟MD5校正。
if ($isCheckMd5) {
$contentMd5 = OssUtil::getMd5SumForFile($uploadFile, $fromPos, $toPos);
$upOptions[$ossClient::OSS_CONTENT_MD5] = $contentMd5;
}
try {
// 上傳分區。
$responseUploadPart[] = $ossClient->uploadPart($bucket, $object, $uploadId, $upOptions);
printf("initiateMultipartUpload, uploadPart - part#{$i} OK\n");
} catch(OssException $e) {
printf("initiateMultipartUpload, uploadPart - part#{$i} FAILED\n");
printf($e->getMessage() . "\n");
return;
}
}
// $uploadParts是由每個分區的ETag和分區號(PartNumber)組成的數組。
$uploadParts = array();
foreach ($responseUploadPart as $i => $eTag) {
$uploadParts[] = array(
'PartNumber' => ($i + 1),
'ETag' => $eTag,
);
}
/**
* 步驟3:完成上傳。
*/
$comOptions['headers'] = array(
// 指定完成分區上傳時是否覆蓋同名Object。此處設定為true,表示禁止覆蓋同名Object。
// 'x-oss-forbid-overwrite' => 'true',
// 如果指定了x-oss-complete-all:yes,則OSS會列舉當前uploadId已上傳的所有Part,然後按照PartNumber的序號排序並執行CompleteMultipartUpload操作。
// 'x-oss-complete-all'=> 'yes'
);
try {
// 執行completeMultipartUpload操作時,需要提供所有有效$uploadParts。OSS收到提交的$uploadParts後,會逐一驗證每個分區的有效性。當所有的資料分區驗證通過後,OSS將把這些分區組合成一個完整的檔案。
$ossClient->completeMultipartUpload($bucket, $object, $uploadId, $uploadParts,$comOptions);
printf( "Complete Multipart Upload OK\n");
} catch(OssException $e) {
printf("Complete Multipart Upload FAILED\n");
printf($e->getMessage() . "\n");
return;
}
分區上傳本地檔案
以下代碼用於分區上傳本地檔案到OSS。
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
}
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\CoreOssException;
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
$endpoint = 'https://oss-cn-hangzhou.aliyuncs.com';
// 填寫Bucket名稱,例如examplebucket。
$bucket= 'examplebucket';
//填寫不包含Bucket名稱在內的Object完整路徑,例如exampledir/exampleobject.txt。
$object = 'exampledir/exampleobject.txt';
// 填寫本地檔案的完整路徑。
$file = 'D:\\localpath\\examplefile.txt';
$options = array(
OssClient::OSS_CHECK_MD5 => true,
OssClient::OSS_PART_SIZE => 1,
);
try{
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
"region"=> "cn-hangzhou"
);
$ossClient = new OssClient($config);
$ossClient->multiuploadFile($bucket, $object, $file, $options);
} catch(OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
print(__FUNCTION__ . ": OK" . "\n");
分區上傳目錄
以下代碼用於分區上傳本地目錄(包含此目錄下的所有檔案)到OSS。
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
}
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\CoreOssException;
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
$endpoint = 'https://oss-cn-hangzhou.aliyuncs.com';
// 填寫Bucket名稱,例如examplebucket。
$bucket= 'examplebucket';
// 填寫待上傳的本地目錄的完整路徑。
$localDirectory = "D:\\localpath";
// 填寫上傳至OSS的目錄首碼。
$prefix = "samples/codes/";
try {
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
"region"=> "cn-hangzhou"
);
$ossClient = new OssClient($config);
$ossClient->uploadDir($bucket, $prefix, $localDirectory);
} catch(OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
print(__FUNCTION__ . ": OK" . "\n");
取消分區上傳事件
您可以調用$ossClient->abortMultipartUpload方法來取消分區上傳事件。當一個分區上傳事件被取消後,無法再使用此uploadId做任何操作,已經上傳的分區資料會被刪除。
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
}
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\CoreOssException;
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
$endpoint = 'https://oss-cn-hangzhou.aliyuncs.com';
// 填寫Bucket名稱,例如examplebucket。
$bucket= 'examplebucket';
//填寫不包含Bucket名稱在內的Object完整路徑,例如exampledir/exampleobject.txt。
$object = 'exampledir/exampleobject.txt';
// 填寫uploadId,例如0004B999EF518A1FE585B0C9360D****。uploadId來源於調用InitiateMultipartUpload完成初始化分區之後的返回結果。
$upload_id = '0004B999EF518A1FE585B0C9360D****';
try{
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
"region"=> "cn-hangzhou"
);
$ossClient = new OssClient($config);
$ossClient->abortMultipartUpload($bucket, $object, $upload_id);
} catch(OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
print(__FUNCTION__ . ": OK" . "\n");
列舉已上傳的分區
調用listParts方法列舉出指定uploadId下所有已經上傳成功的分區。
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
}
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\CoreOssException;
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
$endpoint = 'https://oss-cn-hangzhou.aliyuncs.com';
// 填寫Bucket名稱,例如examplebucket。
$bucket= 'examplebucket';
//填寫不包含Bucket名稱在內的Object完整路徑,例如exampledir/exampleobject.txt。
$object = 'exampledir/exampleobject.txt';
// 填寫uploadId,例如0004B999EF518A1FE585B0C9360D****。uploadId來源於調用InitiateMultipartUpload完成初始化分區之後,且在調用CompleteMultipartUpload完成分區上傳之前的返回結果。
$upload_id = '0004B999EF518A1FE585B0C9360D****';
try{
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
"region"=> "cn-hangzhou"
);
$ossClient = new OssClient($config);
$listPartsInfo = $ossClient->listParts($bucket, $object, $uploadId);
foreach ($listPartsInfo->getListPart() as $partInfo) {
print($partInfo->getPartNumber() . "\t" . $partInfo->getSize() . "\t" . $partInfo->getETag() . "\t" . $partInfo->getLastModified() . "\n");
}
} catch(OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
print(__FUNCTION__ . ": OK" . "\n");
列舉分區上傳事件
調用listMultipartUploads方法列舉出所有執行中的分區上傳事件,即已初始化但還未完成(Complete)或者還未中止(Abort)的分區上傳事件。
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
require_once __DIR__ . '/../vendor/autoload.php';
}
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\CoreOssException;
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
$endpoint = 'https://oss-cn-hangzhou.aliyuncs.com';
// 填寫Bucket名稱,例如examplebucket。
$bucket= 'examplebucket';
$options = array(
'delimiter' => '/',
'max-uploads' => 100,
'key-marker' => '',
'prefix' => '',
'upload-id-marker' => ''
);
try {
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
"region"=> "cn-hangzhou"
);
$ossClient = new OssClient($config);
$listMultipartUploadInfo = $ossClient->listMultipartUploads($bucket, $options);
} catch(OssException $e) {
printf(__FUNCTION__ . ": listMultipartUploads FAILED\n");
printf($e->getMessage() . "\n");
return;
}
printf(__FUNCTION__ . ": listMultipartUploads OK\n");
$listUploadInfo = $listMultipartUploadInfo->getUploads();
var_dump($listUploadInfo);
$options的參數說明請參見下表。
參數 | 說明 |
delimiter | 用於對檔案名稱進行分組的一個字元。所有檔案名稱包含指定的首碼且第一次出現delimiter字元之間的檔案作為一組元素。 |
key-marker | 所有檔案名稱的字典序大於key-marker參數值的分區上傳事件。與upload-id-marker參數一同使用,用於指定返回結果的起始位置。 |
max-uploads | 限定此次返回分區上傳事件的最大個數,預設值和最大值均為1000。 |
prefix | 限定返回的檔案名稱必須以指定的prefix作為首碼。 說明 使用prefix查詢時,返回的檔案名稱中仍會包含prefix。 |
upload-id-marker | 與key-marker參數一同使用,用於指定返回結果的起始位置。 如果未設定key-marker參數,則此參數無效。如果設定了key-marker參數,則查詢結果中包含:
|
相關文檔
關於分區上傳的完整範例程式碼,請參見GitHub樣本。
分區上傳的完整實現涉及三個API介面,詳情如下:
關於初始化分區上傳事件的API介面說明,請參見InitiateMultipartUpload。
關於分區上傳Part的API介面說明,請參見UploadPart。
關於完成分區上傳的API介面說明,請參見CompleteMultipartUpload。
關於取消分區上傳事件的API介面說明,請參見AbortMultipartUpload。
關於列舉已上傳分區的API介面說明,請參見ListParts。
關於列舉所有執行中的分區上傳事件(即已初始化但尚未完成或已取消的分區上傳事件)的API介面說明,請參見ListMultipartUploads。