如何在CURL下载文件时使用CURLOPT_WRITEFUNCTION

My Class for download file direct from a link:

MyClass{

          function download($link){
                ......
                $ch = curl_init($link);
                curl_setopt($ch, CURLOPT_FILE, $File->handle);
                curl_setopt($ch,CURLOPT_WRITEFUNCTION , array($this,'__writeFunction'));
                curl_exec($ch);
                curl_close($ch);
                $File->close();
                ......

            }

          function __writeFunction($curl, $data) {
                return strlen($data);            
          } 
}

I want know how to use CRULOPT_WRITEFUNCTION when download file. Above code if i remove line:

curl_setopt($ch,CURLOPT_WRITEFUNCTION , array($this,'__writeFunction'));

Then it will run good, i can download that file.But if i use CURL_WRITEFUNCTION option i can't download file.

Why do you use curl to download a file? Is there a special reason? You can simply use fopen and fread

I have written a small class for it.

<?php
class Utils_FileDownload  {
    private $source;
    private $dest;
    private $buffer;
    private $overwrite;
    public function __construct($source,$dest,$buffer=4096,$overwrite=false){
        $this->source = $source;
        $this->dest   = $dest;
        $this->buffer = $buffer; 
        $this->overwrite = $overwrite;
    }
    public function download(){
        if($this->overwrite||!file_exists($this->dest)){
            if(!is_dir(dirname($this->dest))){mkdir(dirname($this->dest),0755,true);}
            if($this->source==""){
                $resource = false;
                Utils_Logging_Logger::getLogger()->log("source must not be empty.",Utils_Logging_Logger::TYPE_ERROR);
            }
            else{ $resource = fopen($this->source,"rb"); }
            if($this->source==""){
                $dest = false;
                Utils_Logging_Logger::getLogger()->log("destination must not be empty.",Utils_Logging_Logger::TYPE_ERROR);
            }
            else{ $dest     = fopen($this->dest,"wb"); }
            if($resource!==false&&$dest!==false){
                while(!feof($resource)){
                    $read = fread($resource,$this->buffer);
                    fwrite($dest,$read,$this->buffer);
                }
                chmod($this->dest,0644);
                fclose($dest); fclose($resource);
                return true;
            }else{
                 return false;   
            }
        }else{
            return false;
        }
    }
}
<?php 
$ch = curl_init();
curl_setopt($ch, CURLOPT_BUFFERSIZE, 8096);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_URL, 'http://blog.ronnyristau.de/wp-content/uploads/2008/12/php.jpg');

$content = curl_exec($ch);

curl_close($ch);

$out = fopen('/tmp/out.png','w');
if($out){
    fwrite($out, $content);
    fclose($out);
}

I know this is an old question, but maybe my answer will be of some help for you or someone else. Try this:

function get_write_function(){
    return function($curl, $data){
        return strlen($data);
    }
}

I don't know exactly what you want to do, but with PHP 5.3, you can do a lot with the callback. What's really great about generating a function in this way is that the values passed through the 'use' keyword remain with the function afterward, kind of like constants.

function get_write_function($var){
    $obj = $this;//access variables or functions within your class with the object variable
    return function($curl, $data) use ($var, $obj) {
        $len = strlen($data);
        //just an example - you can come up with something better than this:
        if ($len > $var){
            return -1;//abort the download
        } else {
            $obj->do_something();//call a class function
            return $len;
        }
    }
}

You can retrieve the function as a variable as follows:

function download($link){
    ......
    $var = 5000;
    $write_function = $this->get_write_function($var);
    $ch = curl_init($link);
    curl_setopt($ch, CURLOPT_FILE, $File->handle);
    curl_setopt($ch, CURLOPT_WRITEFUNCTION , $write_function);
    curl_exec($ch);
    curl_close($ch);
    $File->close();
    ......

}

That was just an example. You can see how I used it here: Parallel cURL Request with WRITEFUNCTION Callback. I didn't actually test all of this code, so there may be minor errors. Let me know if you have problems, and I'll fix it.

It seems like cURL uses your function instead of writing to the request once CURLOPT_WRITEFUNCTION is specified.

So the correct solution would be :

MyClass{

      function download($link){
            ......
            $ch = curl_init($link);
            curl_setopt($ch, CURLOPT_FILE, $File->handle);
            curl_setopt($ch,CURLOPT_WRITEFUNCTION , array($this,'__writeFunction'));
            curl_exec($ch);
            curl_close($ch);
            $File->close();
            ......

        }

      function __writeFunction($curl, $data) {
            echo $data;
            return strlen($data);            
      } 
}

This can also handle binary files as well.