【问题标题】:Downloading big files and writing it locally下载大文件并在本地写入
【发布时间】:2011-06-27 22:12:31
【问题描述】:

在不消耗所有服务器内存的情况下,从php下载大文件的最佳方法是什么?

我可以这样做(错误的代码):

$url='http://server/bigfile';
$cont = file_get_contents($url);
file_put_contents('./localfile',$cont);

此示例在$cont 中加载入口远程文件,这可能会超出内存限制。

是否有一个安全的函数(可能是内置的)来执行此操作(可能是 stream_*)?

谢谢

【问题讨论】:

  • 对那个 Q 的回答不好
  • 是的。接受的答案(使用 fsockopen 的海报)是 PHP 中此类事物的一种有效解决方案。不是因为您认为答案不好,就证明创建问题的副本是合理的。你有足够的代表,为什么不开始赏金呢?

标签: php


【解决方案1】:

您可以使用 curl 和选项 CURLOPT_FILE 将下载的内容直接保存到文件中。

set_time_limit(0);
$fp = fopen ('file', 'w+b');
$ch = curl_init('http://remote_url/file');
curl_setopt($ch, CURLOPT_TIMEOUT, 75);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_exec($ch);
curl_close($ch);
fclose($fp);

【讨论】:

  • 为什么要设置timeout和returntransfer? (source)
  • @yes123 实际上你是对的 RETURNTRANSFER 可能没有必要。我把超时放在那里供参考,如果你不希望你的脚本永远运行,它可能值得使用。 (即网络速度可能比预期的慢)。对于您的传输时间,可能还有一个默认值太低。因此,将其设置为较高的值或 0 可能是值得的。
【解决方案2】:

这是我在下载大文件时使用的功能。它将避免将整个文件加载到缓冲区中。相反,它会在接收字节时写入目标。

function download($file_source, $file_target) 
{
    $rh = fopen($file_source, 'rb');
    $wh = fopen($file_target, 'wb');
    if (!$rh || !$wh) {
        return false;
    }

    while (!feof($rh)) {
        if (fwrite($wh, fread($rh, 1024)) === FALSE) {
            return false;
        }
    }

    fclose($rh);
    fclose($wh);

    return true;
}

【讨论】:

  • 我觉得这个功能不错。此时的选择是在这样的函数或使用 curl 直接流写入之间
  • 不同之处在于cURL会在写入之前将整个文件加载到内存中(除非我的内存出卖了我)。
  • 我不认为.. 使用curl_setopt($ch, CURLOPT_FILE, $fp); 可以避免内存使用
  • 我很好奇为什么你接受了 cURL 解决方案,因为它不能解决你的主要问题,即使用更多内存。 耸耸肩
  • 阅读我上面的评论。如果您设置CURLOPT_FILE,您将避免使用内存
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-02
  • 2016-09-05
  • 2013-10-18
  • 2019-01-19
相关资源
最近更新 更多