tags:

views:

386

answers:

4

Task

Downloading binary files from a remote media processing server to a web server.

This works but I cannot capture the curl stdout output

$result = shell_exec('curl -v http://domain.com/images/dir/dir/dir/file.jpg --user username:password -o /usr/www/htdocs/images/dir/dir/dir/file.jpg');

Note: I have had no luck using the PHP curl wrapper methods for this task, partly because I've never used PHP curl wrappers for FTP downloads.

Question Can someone explain how to capture the output from the command that I am shelling out to or a simple example using PHP curl wrappers?

Here is what I tried and the part I'm stumped on is how to get the new file placed on the target server - The line that's wrong is the CURLOPT_FILE line. I don't want to have to create a stub file, open it and then write to it.

$curl = curl_init();

curl_setopt($curl, CURLOPT_URL, $ftpserver.$file['directory'].$filename); #input
curl_setopt($curl, CURLOPT_FILE, $dest); #output
curl_setopt($curl, CURLOPT_USERPWD, "$user:$password");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);

Thanks

A: 

$dest needs to be a file resource opened via

$dest = fopen("filename.ext", "w");

does that work for you?

Janek
Probably would work however I want to avoid creating a stub file and then writing to it. I am certain that my line "...CURLOPT_FILE" is not right, since the file doesn't exist on the source machine
Slinky
A: 

According to a comment in the PHP manual, you must be sure to close your curl stream AND your file handler before the file is written properly. I'll copy the example here for search purposes:

<?php

$fh = fopen('/tmp/foo', 'w');
$ch = curl_init('http://example.com/foo');
curl_setopt($ch, CURLOPT_FILE, $fh);
curl_exec($ch);
curl_close($ch);

# at this point your file is not complete and corrupted

fclose($fh);

# now you can use your file;

read_file('/tmp/foo');

?>

Also, I would debate the merits of using CURLOPT_RETURNTRANSFER with CURLOPT_FILE, as CURLOPT_RETURNTRANSFER tells curl to return the fetched results as the result of curl_exec(). You probably don't need that if you're just writing it to a file.

zombat
I agree. That should not be there
Slinky
A: 

This fixed it by redirecting stdout output: 2>&1

So this works: $result = shell_exec('curl -v http://domain.com/images/dir/dir/dir/file.jpg --user username:password -o /usr/www/htdocs/images/dir/dir/dir/file.jpg 2>&1');

It would be great to be able to use the PHP curl wrappers but not if it means opening a stub file on the source machine and then writing to it. The curl command line version just moves over the file, nice and neat. If anyone knows how to do what I'm trying to do using PHP wrappers, I'd love to see how you do it.

Slinky
A: 
    /**
*Downloads a binary file into a string
*@param string $file URL's file 
*@param string $ref  Referer
*@return string $downloaded_binary string containing the binary file
*/
function download_file($file, $ref)
{
 $curl_obj = curl_init();    
 curl_setopt($curl_obj, CURLOPT_URL, $file);
 curl_setopt($curl_obj, CURLOPT_REFERER, $ref);
     curl_setopt($curl_obj, CURLOPT_BINARYTRANSFER, 1);
     curl_setopt($curl_obj, CURLOPT_RETURNTRANSFER, TRUE);
 curl_setopt($curl_obj, CURLOPT_MAXREDIRS, SPDR_MAX_REDIR);                           
 curl_setopt($curl_obj, CURLOPT_FOLLOWLOCATION, TRUE); //followlocation cannot be used when safe_mode/open_basedir are on
 curl_setopt($curl_obj, CURLOPT_SSL_VERIFYPEER, FALSE);               
     $downloaded_binary = curl_exec($curl_obj);    

     curl_close($curl_obj);
     return $downloaded_binary;
}
pcp