Multipart upload splits a large object into multiple parts and uploads them independently. After all parts are uploaded, call CompleteMultipartUpload to assemble them into a single object.
Prerequisites
Before you begin, ensure that you have:
An OSS bucket in the target region
The
oss:PutObjectpermission on the bucket — see Grant custom access policies to a RAM userAccess Key ID and Access Key Secret stored as environment variables — see Configure access credentials for PHP
How it works
A multipart upload follows three steps:
Initiate — Call
InitiateMultipartUploadto get a globally unique upload ID from OSS.Upload parts — Call
UploadPartonce for each part, passing the upload ID and a part number.Complete — Call
CompleteMultipartUploadwith the list of uploaded parts to assemble the final object.
Part upload behavior:
Uploading a new part with an existing part number overwrites the previous data for that part.
OSS returns the MD5 hash of each received part in the
ETagresponse header.OSS validates integrity by comparing the MD5 it calculates against the SDK-calculated value. A mismatch returns an
InvalidDigesterror.
Upload a large file in parts
The following example splits a local file into 5 MB parts, uploads each part sequentially, and completes the upload. The endpoint is set to cn-hangzhou (public endpoint). If you access OSS from another Alibaba Cloud service in the same region, use the internal endpoint instead.
<?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)
);Replace the following placeholders before running the code:
| Placeholder | Description |
|---|---|
/Users/yourLocalPath/yourFileName | Absolute path to the local file you want to upload |
--region argument | Region ID of your bucket, for example cn-hangzhou |
--bucket argument | Name of your target bucket |
--key argument | Object key (name) to assign in OSS |
Upload with a callback
To notify an application server after the upload completes, attach an upload callback to CompleteMultipartUpload. The initiation and part-upload steps are identical to the basic example above — only the completion call changes.
<?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)
);Related topics
For the complete sample code, see the GitHub sample.
For all supported regions and their endpoints, see OSS regions and endpoints.