All Products
Search
Document Center

Object Storage Service:Unggah multi-bagian (PHP SDK V2)

Last Updated:Mar 21, 2026

Unggah multi-bagian membagi objek besar menjadi beberapa bagian dan mengunggahnya secara independen. Setelah semua bagian diunggah, panggil CompleteMultipartUpload untuk menyusunnya menjadi satu objek tunggal.

Prasyarat

Sebelum memulai, pastikan Anda telah memiliki:

Cara kerja

Unggah multi-bagian mengikuti tiga langkah:

  1. Initiate — Panggil InitiateMultipartUpload untuk mendapatkan upload ID yang unik secara global dari OSS.

  2. Upload parts — Panggil UploadPart sekali untuk setiap bagian, dengan menyertakan upload ID dan nomor bagian.

  3. Complete — Panggil CompleteMultipartUpload dengan daftar bagian yang telah diunggah untuk menyusun objek akhir.

Perilaku unggah bagian:

  • Mengunggah bagian baru dengan nomor bagian yang sudah ada akan menimpa data sebelumnya untuk bagian tersebut.

  • OSS mengembalikan hash MD5 dari setiap bagian yang diterima dalam header respons ETag.

  • OSS memvalidasi integritas dengan membandingkan hash MD5 yang dihitungnya terhadap nilai yang dihitung oleh SDK. Ketidakcocokan akan menghasilkan error InvalidDigest.

Unggah file besar dalam beberapa bagian

Contoh berikut membagi file lokal menjadi bagian-bagian berukuran 5 MB, mengunggah setiap bagian secara berurutan, lalu menyelesaikan proses unggah. Titik akhir diatur ke cn-hangzhou (titik akhir publik). Jika Anda mengakses OSS dari layanan Alibaba Cloud lain di wilayah yang sama, gunakan titik akhir internal sebagai gantinya.

<?php

require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// Parse required command-line arguments: --region, --bucket, --key
// Optional: --endpoint
$optsdesc = [
    "region"   => ['help' => 'The region in which the bucket is located.', 'required' => True],
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False],
    "bucket"   => ['help' => 'The name of the bucket', 'required' => True],
    "key"      => ['help' => 'The name of the object', 'required' => True],
];

$longopts = \array_map(function ($key) { return "$key:"; }, array_keys($optsdesc));
$options  = getopt("", $longopts);

foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        echo "Error: the following arguments are required: --$key, " . $value['help'] . PHP_EOL;
        exit(1);
    }
}

$region = $options["region"];
$bucket = $options["bucket"];
$key    = $options["key"];

// Load credentials from environment variables OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider);
$cfg->setRegion($region);
$cfg->setEndpoint('http://oss-cn-hangzhou.aliyuncs.com');

$client = new Oss\Client($cfg);

// Step 1: Initiate the multipart upload and obtain an upload ID
$initResult = $client->initiateMultipartUpload(
    new Oss\Models\InitiateMultipartUploadRequest(
        bucket: $bucket,
        key: $key
    )
);

// Step 2: Split the file and upload each part
$bigFileName = "/Users/yourLocalPath/yourFileName"; // Replace with the path to your local file
$partSize    = 5 * 1024 * 1024;                     // 5 MB per part
$fileSize    = filesize($bigFileName);
$partsNum    = intdiv($fileSize, $partSize) + intval(1);
$parts       = [];

$i    = 1;
$file = new \GuzzleHttp\Psr7\LazyOpenStream($bigFileName, 'rb');

while ($i <= $partsNum) {
    $partResult = $client->uploadPart(
        new Oss\Models\UploadPartRequest(
            bucket:        $bucket,
            key:           $key,
            partNumber:    $i,
            uploadId:      $initResult->uploadId,
            contentLength: null,   // Optional: length of the part body
            contentMd5:    null,   // Optional: The MD5 hash of the part content for validation.
            trafficLimit:  null,   // Optional: The traffic limit.
            requestPayer:  null,   // Optional: The requester pays for the request.
            body:          new \GuzzleHttp\Psr7\LimitStream($file, $partSize, ($i - 1) * $partSize)
        )
    );

    // Collect the part number and ETag — both are required to complete the upload
    $parts[] = new Oss\Models\UploadPart(
        partNumber: $i,
        etag:       $partResult->etag
    );

    $i++;
}

// Step 3: Assemble all parts into the final object
$comResult = $client->completeMultipartUpload(
    new Oss\Models\CompleteMultipartUploadRequest(
        bucket:                  $bucket,
        key:                     $key,
        uploadId:                $initResult->uploadId,
        acl:                     null, // Optional: set the ACL of the assembled object
        completeMultipartUpload: new Oss\Models\CompleteMultipartUpload(
            parts: $parts
        )
    )
);

printf(
    'status code: %s' . PHP_EOL .
    'request ID: %s' . PHP_EOL .
    'result: %s' . PHP_EOL,
    $comResult->statusCode,
    $comResult->requestId,
    var_export($comResult, true)
);

Ganti placeholder berikut sebelum menjalankan kode:

PlaceholderDeskripsi
/Users/yourLocalPath/yourFileNameJalur absolut ke file lokal yang ingin Anda unggah
--region argumentID wilayah bucket Anda, contohnya cn-hangzhou
--bucket argumentNama bucket tujuan Anda
--key argumentKunci objek (nama) yang akan digunakan di OSS

Unggah dengan callback

Untuk memberi notifikasi ke server aplikasi setelah unggah selesai, tambahkan upload callback ke CompleteMultipartUpload. Langkah inisiasi dan unggah bagian identik dengan contoh dasar di atas — hanya pemanggilan penyelesaian yang berubah.

<?php

require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

$optsdesc = [
    "region"   => ['help' => 'The region in which the bucket is located.', 'required' => True],
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False],
    "bucket"   => ['help' => 'The name of the bucket', 'required' => True],
    "key"      => ['help' => 'The name of the object', 'required' => True],
];

$longopts = \array_map(function ($key) { return "$key:"; }, array_keys($optsdesc));
$options  = getopt("", $longopts);

foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        echo "Error: the following arguments are required: --$key, " . $value['help'] . PHP_EOL;
        exit(1);
    }
}

$region = $options["region"];
$bucket = $options["bucket"];
$key    = $options["key"];

$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider);
$cfg->setRegion($region);
$cfg->setEndpoint('http://oss-cn-hangzhou.aliyuncs.com');

$client = new Oss\Client($cfg);

// Initiate
$initResult = $client->initiateMultipartUpload(
    new Oss\Models\InitiateMultipartUploadRequest(
        bucket: $bucket,
        key: $key
    )
);

// Upload parts (same logic as the basic example)
$bigFileName = "/Users/yourLocalPath/yourFileName";
$partSize    = 5 * 1024 * 1024;
$fileSize    = filesize($bigFileName);
$partsNum    = intdiv($fileSize, $partSize) + intval(1);
$parts       = [];

$i    = 1;
$file = new \GuzzleHttp\Psr7\LazyOpenStream($bigFileName, 'rb');

while ($i <= $partsNum) {
    $partResult = $client->uploadPart(
        new Oss\Models\UploadPartRequest(
            bucket:        $bucket,
            key:           $key,
            partNumber:    $i,
            uploadId:      $initResult->uploadId,
            contentLength: null,
            contentMd5:    null,
            trafficLimit:  null,
            requestPayer:  null,
            body:          new \GuzzleHttp\Psr7\LimitStream($file, $partSize, ($i - 1) * $partSize)
        )
    );

    $parts[] = new Oss\Models\UploadPart(
        partNumber: $i,
        etag:       $partResult->etag
    );

    $i++;
}

// Build the callback payload — OSS will POST this to your server after assembly
$call_back_url = "http://www.example.com/callback"; // Replace with your server's endpoint

// The callback body uses OSS system variables ({bucket}, {object}) and
// custom variables ({x:var1}, {x:var2}) that you define in callbackVar.
$callback_body_template = "bucket={bucket}&object={object}&my_var_1={var1}&my_var_2={var2}";
$callback_body = str_replace(
    ['{bucket}', '{object}', '{var1}', '{var2}'],
    [$bucket, $key, 'value1', 'value2'],
    $callback_body_template
);

// Both callback and callbackVar must be Base64-encoded JSON
$callback = base64_encode(json_encode([
    "callbackUrl"  => $call_back_url,
    "callbackBody" => $callback_body,
]));

$callback_var = base64_encode(json_encode([
    "x:var1" => "value1",
    "x:var2" => "value2",
]));

// Complete — OSS triggers the callback after assembling the object
$comResult = $client->completeMultipartUpload(
    new Oss\Models\CompleteMultipartUploadRequest(
        bucket:                  $bucket,
        key:                     $key,
        uploadId:                $initResult->uploadId,
        acl:                     null,
        completeMultipartUpload: new Oss\Models\CompleteMultipartUpload(
            parts: $parts
        ),
        callback:    $callback,
        callbackVar: $callback_var,
    )
);

printf(
    'status code: %s' . PHP_EOL .
    'request ID: %s' . PHP_EOL .
    'result: %s' . PHP_EOL,
    $comResult->statusCode,
    $comResult->requestId,
    var_export($comResult, true)
);

Topik terkait