2

which is the best way to download from php large files without consuming all server's memory?

I could do this (bad code):

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

This example loads entry remote file in $cont and this could exceed memory limit.

Is there a safe function (maybe built-in) to do this (maybe stream_*)?

Thanks

  • 2
    duplicate: http://stackoverflow.com/questions/4000483/php-how-download-big-file-using-php-low-memory-usage – KJYe.Name Feb 15 '11 at 21:06
  • answers on that Q aren't good –  Feb 15 '11 at 21:17
  • Yes they are. The accepted answer (poster used fsockopen) is one valid solution for that type of thing in PHP. Not because you don't think the answers aren't good that it justifies creating a duplicate of a question. You have enough rep, why not start a bounty? – netcoder Feb 15 '11 at 21:41

2 Answers2

6

You can use curl and the option CURLOPT_FILE to save the downloaded content directly to a 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);
hanshenrik
  • 19,904
  • 4
  • 43
  • 89
GWW
  • 43,129
  • 11
  • 115
  • 108
  • why do you set timeout and returntransfer? ([source](http://www.phpriot.com/articles/download-with-curl-and-php)) – dynamic Feb 15 '11 at 21:20
  • @yes123 actually you are right RETURNTRANSFER is probably not necessary. I put the timeout there for reference, it may be worth using it if you don't want your script to run forever. (Ie. maybe the network speed is slower than expected). There may be a default value for that is too low for your transfer time as well. So it may be worthwhile setting that to a high value or 0. – GWW Feb 15 '11 at 21:24
6

Here is a function I use when downloading large files. It will avoid loading the entire file into the buffer. Instead, it will write to the destination as it receives the bytes.

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;
}
John Cartwright
  • 5,109
  • 22
  • 25