从 URL 下载大图像到 PHP 服务器的高性能方法

High performance method for downloading large images to PHP server from URL

我有一个包含大约 100 个图像链接的数组。图片大约 5-10 MB。我想遍历数组并将所有图片下载到我的服务器。我找到了几种方法,并从 file_get_contents 开始,但它占用了我的记忆。

我也看过

Wget

shell_exec('wget -O /var/www/html/images/image.gif http://www.google.com/images/logo_sm.gif');

PHP复制

copy('http://example.com/image.php', 'local/folder/flower.jpg');

CULR

$url  = 'http://www.google.com/images/logo_sm.gif';
$path = '/var/www/html/images/images.gif';

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$data = curl_exec($ch);

curl_close($ch);

file_put_contents($path, $data);

每个用户都有自己的 "own" 数组(不同的图像链接)。将图片下载到我的服务器并要求最低性能(低内存使用率等)的最快方法是什么

计时 cURL/wget/copy 方法并查看:它们将具有 "roughly the same" 吞吐量并且不会使用过多内存1。然而,

这些新方法遇到同样的问题;下载按顺序进行。

(虽然涉及许多因素,包括 bandwidth/latency 和 servers/handlers 之间的分布, 添加一定程度的并行性将是改进总吞吐量.)

wget + 并行生成

start generic parallel processes 有几种方法可以与 shell_exec 和 wget 一起使用。这些方法可以并行生成 (wget) 进程。

由于无法直接访问特定进程正在执行的操作,因此还涉及欺骗输出 redirection/processing。另一方面,它是一次 'relatively simple' 一次 shell 执行的更改。

shell exec 本身也应该针对注入攻击进行加固;使用此类 shell 访问权限时,不应降低安全性。

cURL + 多执行

更有利可图(并且最初很复杂)的方法是使用 curl_multi_exec。与curl_exec不同,multi exec允许以异步方式处理curl,从而支持并行操作。

过程有点曲折,但是a generic example can be found here;还有一些关于 SO 的相关问题(尽管我还没有找到针对这个特定问题的 'killer question/answer'):

  • understanding php curl_multi_exec
  • Fastest way to download multiple urls

实现可能还想限制并行 cURL 请求的数量。

我推荐 cURL,因为它避免了在处理 shell 时必须是 'extra careful'。如果必须使用 shell exec,那么考虑先将文件 list/targets 保存到一个文件中,然后通过 xargs 或诸如此类的东西将其输入。使用 cURL 还允许对单个请求进行关联反馈。

由于此操作可能绑定到 'take some time',因此下载可能应该通过队列/非请求机制来完成。但那是一种不同的蠕虫架构。


1 file_get_contents 的问题是它将下载的数据作为字符串获取,这可能导致 'out of memory' 条件,具体取决于文件大小和 PHP环境。

但是,none 的 cURL/wget/open 方法(如果正确完成)在直接流式传输到文件时会遇到此问题。 (在这个问题中,cURL 可能 运行 内存不足,因为它没有正确地流式传输到文件,而是在整个文件已经下载到内存中后调用 file_put_contents。)