全部產品
Search
文件中心

Object Storage Service:PHP上傳檔案

更新時間:Jun 19, 2024

本文介紹如何在受版本控制的儲存空間(Bucket)中上傳檔案(Object)。

注意事項

  • 本文以華東1(杭州)外網Endpoint為例。如果您希望通過與OSS同地區的其他阿里雲產品訪問OSS,請使用內網Endpoint。關於OSS支援的Region與Endpoint的對應關係,請參見訪問網域名稱和資料中心

  • 本文以OSS網域名稱建立OSSClient為例。如果您希望通過自訂網域名、STS等方式建立OSSClient,請參見建立OssClient

  • 要上傳檔案,您必須有oss:PutObject許可權。具體操作,請參見為RAM使用者授權自訂的權限原則

簡單上傳

在已開啟版本控制的Bucket中,OSS將為新上傳的Object產生全域唯一的隨機字串版本ID,並在響應Header中通過x-oss-version-id形式返回。

在暫停了版本控制的Bucket中,OSS將為新上傳的Object產生特殊字元串為“null”的版本ID。上傳同名Object時,後一次會覆蓋前一次上傳的檔案內容,即同一個Object僅有一個版本的ID為“null”。

以下代碼用於簡單上傳:

<?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以杭州為例,其它Region請按實際情況填寫。
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
$bucket= "<yourBucketName>";
// 填寫不包含Bucket名稱在內的Object的完整路徑,例如example/test.txt。
$object = "<yourObjectName>";
$content = "hello world";

$config = array(
        "provider" => $provider,
        "endpoint" => $endpoint,
    );
    $ossClient = new OssClient($config);

try {
    // 在受版本控制的Bucket中上傳Object。
    $ret = $ossClient->putObject($bucket, $object, $content);

    // 查看Object的版本資訊。
    print("versionId:" .$ret[OssClient::OSS_HEADER_VERSION_ID]);
} catch (OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}

print(__FUNCTION__ . ": OK" . "\n");

簡單上傳的詳細資料請參見PutObject

追加上傳

在受版本控制的Bucket中對Object進行追加上傳(AppendObject)操作時,有如下注意事項:

  • 僅支援對目前的版本為Appendable類型的Object執行AppendObject操作。

  • 不支援對歷史版本為Appendable類型或目前的版本為非Appendable類型的Object(包括Normal Object、Delete Marker等)執行AppendObject操作。

  • 對目前的版本為Appendable類型的Object執行AppendObject操作時,OSS不會為該Appendable類型的Object產生歷史版本。

  • 對目前的版本為Appendable類型的Object執行PutObject或DeleteObject操作時,OSS會將該Appendable類型的Object保留為歷史版本,且該Object不允許繼續追加。

以下代碼用於追加上傳:

<?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以杭州為例,其它Region請按實際情況填寫。
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
$bucket= "<yourBucketName>";
$object = "<yourObjectName>";
// 表示第一次、第二次以及第三次追加上傳後擷取的檔案內容分別為Hello OSS、Hi OSS以及OSS OK。
$content_array = array('Hello OSS', 'Hi OSS', 'OSS OK');
try{
    $config = array(
        "provider" => $provider,
        "endpoint" => $endpoint,
    );
    $ossClient = new OssClient($config);

    // 第一次追加上傳。第一次追加的位置是0,傳回值為下一次追加的位置。後續追加的位置是追加前檔案的長度。
    $position = $ossClient->appendObject($bucket, $object, $content_array[0], 0);    
    $position = $ossClient->appendObject($bucket, $object, $content_array[1], $position);   
    $position = $ossClient->appendObject($bucket, $object, $content_array[2], $position);
} catch(OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}
print(__FUNCTION__ . ": OK" . "\n");

追加上傳的詳細資料請參見AppendObject

分區上傳

在受版本控制的Bucket中,調用CompleteMultipartUpload介面來完成整個檔案的分區上傳,OSS會為整個檔案產生唯一的版本ID,並在響應Header中以x-oss-version-id的形式返回。

以下代碼用於分區上傳:

<?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以杭州為例,其它Region請按實際情況填寫。
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
$bucket= "<yourBucketName>";
$object = "<yourObjectName>";
// 填寫本地檔案的完整路徑。
$uploadFile = "<yourLocalFile>";

/**
 *  步驟1:初始化一個分區上傳事件,擷取uploadId。
 */
try{
    $config = array(
        "provider" => $provider,
        "endpoint" => $endpoint,
    );
    $ossClient = new OssClient($config);

    // 返回uploadId。uploadId是分區上傳事件的唯一標識。您可以根據uploadId發起相關的操作,如取消分區上傳、查詢分區上傳等。
    $uploadId = $ossClient->initiateMultipartUpload($bucket, $object);
} catch(OssException $e) {
    printf(__FUNCTION__ . ": initiateMultipartUpload FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}
print(__FUNCTION__ . ": initiateMultipartUpload OK" . "\n");
/*
 * 步驟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表示開啟,false表示未開啟。
        $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);
    } catch(OssException $e) {
        printf(__FUNCTION__ . ": initiateMultipartUpload, uploadPart - part#{$i} FAILED\n");
        printf($e->getMessage() . "\n");
        return;
    }
    printf(__FUNCTION__ . ": initiateMultipartUpload, uploadPart - part#{$i} OK\n");
}
// $uploadParts是由每個分區的ETag和分區號(PartNumber)組成的數組。
$uploadParts = array();
foreach ($responseUploadPart as $i => $eTag) {
    $uploadParts[] = array(
        'PartNumber' => ($i + 1),
        'ETag' => $eTag,
    );
}
/**
 * 步驟3:完成上傳。
 */
try {
    // 執行completeMultipartUpload操作時,需要提供所有有效$uploadParts。OSS收到提交的$uploadParts後,會逐一驗證每個分區的有效性。當所有的資料分區驗證通過後,OSS將把這些分區組合成一個完整的檔案。
    $ret = $ossClient->completeMultipartUpload($bucket, $object, $uploadId, $uploadParts);
    // 查看Object版本資訊。
    print("versionId:" .$ret[OssClient::OSS_HEADER_VERSION_ID]);
}  catch(OssException $e) {
    printf(__FUNCTION__ . ": completeMultipartUpload FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}
printf(__FUNCTION__ . ": completeMultipartUpload OK\n");   

分區上傳的詳細資料請參見InitiateMultipartUploadUploadPartCompleteMultipartUpload等介面。