在使用 Guzzle 下载大文件时,为了避免阻塞主进程,可以采用异步请求的方式。Guzzle 提供了异步请求的功能,允许你在下载文件的同时继续执行其他任务。以下是一个使用 Guzzle 异步下载大文件的示例:
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
$client = new Client();
// 发起异步请求
$promise = $client->getAsync('http://example.com/large-file.zip', [
'sink' => '/path/to/save/large-file.zip' // 指定文件保存路径
]);
// 继续执行其他任务
echo "Downloading file in the background...\n";
// 等待异步请求完成
$promise->then(
function ($response) {
echo "File downloaded successfully!\n";
},
function ($exception) {
echo "Download failed: " . $exception->getMessage() . "\n";
}
);
// 保持主进程运行,直到异步请求完成
$promise->wait();
sink
选项在 Guzzle 中,sink
选项允许你将响应内容直接写入文件,而不是将整个文件内容加载到内存中。这对于下载大文件非常有用,因为它可以避免内存耗尽的问题。
Promise
处理多个异步请求如果你需要同时下载多个大文件,可以使用 Promise
来管理多个异步请求:
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
$client = new Client();
$promises = [
'file1' => $client->getAsync('http://example.com/large-file1.zip', ['sink' => '/path/to/save/file1.zip']),
'file2' => $client->getAsync('http://example.com/large-file2.zip', ['sink' => '/path/to/save/file2.zip']),
];
// 等待所有请求完成
$results = Promise\Utils::settle($promises)->wait();
foreach ($results as $key => $result) {
if ($result['state'] === 'fulfilled') {
echo "$key downloaded successfully!\n";
} else {
echo "$key download failed: " . $result['reason']->getMessage() . "\n";
}
}
curl_multi_exec
进行更底层的控制如果你需要更底层的控制,可以使用 PHP 的 curl_multi_exec
函数来实现异步下载。Guzzle 内部也是基于 cURL 的,但如果你需要更精细的控制,可以直接使用 cURL。
如果你在 Web 应用中下载大文件,可以考虑将下载任务放入队列中,使用任务调度器(如 Laravel 的队列系统)在后台处理下载任务,从而避免阻塞主进程。
通过使用 Guzzle 的异步请求功能,你可以避免在下载大文件时阻塞主进程。结合 sink
选项,你可以有效地管理内存使用,确保下载过程不会导致内存耗尽。对于更复杂的场景,可以使用 Promise
来管理多个异步请求,或者使用队列系统来处理后台任务。