Use the Downloader module in OSS SDK for PHP V2 to download large files efficiently with automatic part-based concurrency and resumable download support.
Prerequisites
Before you begin, ensure that you have:
The
oss:GetObjectpermission on the target object. For details, see Grant custom permissions to a RAM user.Access credentials configured as environment variables. For setup instructions, see Configure access credentials for PHP.
Note: The sample code uses the public endpoint for the China (Hangzhou) region (cn-hangzhou). To access OSS from another Alibaba Cloud service in the same region, use the internal endpoint instead. For region and endpoint mappings, see Regions and endpoints.How it works
The Downloader module provides a high-level interface over the GetObject API. Use it when downloading large objects where you want automatic part splitting, concurrent transfers, and fault tolerance — without managing range requests manually.
Part-based concurrency: The Downloader splits the object into parts and downloads them concurrently, improving throughput for large files.
Resumable download: Completed parts are tracked in a breakpoint record file. If a download fails due to a network interruption or an unexpected process exit, the next attempt resumes from the last successful part.
API reference
Class definition
final class Downloader
{
public function __construct($client, array $args = [])
public function downloadFile(
Models\GetObjectRequest $request,
string $filepath,
array $args = []
): Models\DownloadResult
public function downloadTo(
Models\GetObjectRequest $request,
\Psr\Http\Message\StreamInterface $stream,
array $args = []
): Models\DownloadResult
}Parameters
`downloadFile` parameters
| Parameter | Type | Description |
|---|---|---|
request | GetObjectRequest | Object download request. Accepts the same parameters as the GetObject operation. |
filepath | string | Local path to save the downloaded file. |
args | array | (Optional) Configuration options. |
`args` configuration options
| Option | Type | Default | Description |
|---|---|---|---|
part_size | int | 6 MiB | Size of each download part in bytes. |
parallel_num | int | 3 | Number of parts to download concurrently. This is a per-call limit, not a global concurrency limit. |
use_temp_file | bool | true | When true, the object is first downloaded to a temporary file, then renamed to the target path after all parts complete successfully. |
Set configuration options
Pass configuration options at the Downloader instance level or per individual download call.
Instance-level (applies to all downloads from this instance):
$downloader = $client->newDownloader(['part_size' => 10 * 1024 * 1024]);Per-call (overrides instance-level options for that call):
$downloader->downloadFile(
new Oss\Models\GetObjectRequest(bucket: 'bucket', key: 'key'),
filepath: '/local/dir/example',
args: ['part_size' => 10 * 1024 * 1024]
);Download an object to a file
The following example downloads an object from OSS to a local file using the default part size (6 MiB) and concurrency (3 parallel parts).
<?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(fn($key) => "$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);
if (isset($options["endpoint"])) {
$cfg->setEndpoint($options["endpoint"]);
}
$client = new Oss\Client($cfg);
$downloader = $client->newDownloader();
$filename = "/local/path/to/your-file";
touch($filename);
$result = $downloader->downloadFile(
new Oss\Models\GetObjectRequest(
bucket: $bucket,
key: $key
),
$filename
);
printf(
'status code: %s' . PHP_EOL .
'request ID: %s' . PHP_EOL .
'result: %s' . PHP_EOL,
$result->statusCode,
$result->requestId,
var_export($result, true)
);Scenarios
Tune part size and concurrency
Adjust part_size and parallel_num to match your network conditions and performance requirements. Reduce parallel_num in bandwidth-constrained environments to avoid saturating the connection, or increase part_size to reduce the number of requests for very large objects.
The following example sets a 100 KiB part size with a single concurrent download:
<?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(fn($key) => "$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);
if (isset($options["endpoint"])) {
$cfg->setEndpoint($options["endpoint"]);
}
$client = new Oss\Client($cfg);
$downloader = $client->newDownloader();
$filename = "/local/path/to/your-file";
touch($filename);
$result = $downloader->downloadFile(
new Oss\Models\GetObjectRequest(
bucket: $bucket,
key: $key
),
$filename,
args: [
'part_size' => 100 * 1024, // 100 KiB per part
'parallel_num' => 1, // single-threaded download
]
);
printf(
'status code: %s' . PHP_EOL .
'request ID: %s' . PHP_EOL .
'result: %s' . PHP_EOL,
$result->statusCode,
$result->requestId,
var_export($result, true)
);What's next
For a complete runnable example, see the Downloader sample on GitHub.