capturing curl stdout into variable in PHP - php

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

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.

$dest needs to be a file resource opened via
$dest = fopen("filename.ext", "w");
does that work for you?

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.

/**
*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;
}

I think the way to do this is with ob_start().
ob_start();
curl_exec($curl);
$result = ob_get_clean();

Related

Php download file from link that downloads file

I'm trying to use php to download files that are created and downloaded when you call to a url.
In this case i'm trying to programmatically download a txt file from the dutch weather institute wich can be done by going to(in this example) this url http://projects.knmi.nl/klimatologie/daggegevens/getdata_dag.cgi?lang=nl&byear=2016&bmonth=6&bday=20&eyear=2016&emonth=6&eday=22&variabele=FHX&variabele=FXX&variabele=TG&variabele=TN&variabele=TX&stations=249&submit=Download+data+set
Going to that url downloads the file.
I want to do this with php so I can use the contents of the file to make custom charts.
Does anyone know how to do this with php?
Using file_get_contents(): http://php.net/manual/en/function.file-get-contents.php
or using CURL functions: http://php.net/manual/en/function.curl-exec.php
EDIT: CURL Solution:
$url = 'http://projects.knmi.nl/klimatologie/daggegevens/getdata_dag.cgi?lang=nl&byear=2016&bmonth=6&bday=20&eyear=2016&emonth=6&eday=22&variabele=FHX&variabele=FXX&variabele=TG&variabele=TN&variabele=TX&stations=249&submit=Download+data+set';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, false);
$str = curl_exec($curl);
Try:
$content = file_get_contents("The URL here");
echo $content;

cURL script will not download images; Instead renders junk

I have been using the following function to download pictures from a distributor for use on our website as was described here:
$url = "http://covers.stl-distribution.com/7819/lg-9781936417445.jpg";
$itemnum = 80848;
$path = "www.gullions.com/localstore/test/test.jpg";
header('Content-type: image/jpeg');
$ch = curl_init($url);
$fp = fopen("http://www.gullions.com/localstore/test/test.jpg", 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
curl_close($ch);
fclose($fp);
Instead of downloading and saving the picture, it only prints crazy characters to the screen. I know that means that for some reason the browser is trying to render the picture but most likely doesn't recognize the file type. But I can't seem to find the problem. You can see the crazy output by navigating here. To verify that the image wasn't downloaded and saved, you can navigate here. Also, FTP also shows that no file was downloaded. If you navigate to the original picture's download url you'll see that the file we are trying to download does in fact exist.
I have contacted my host and verified that no settings have been changed with the server, that cURL is functioning properly, and have even rolled back my browser to verify that a recent update didn't cause the issue. I created a test file by removing the function from the application and have tried running it separately but have only had the same results.
Add:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
as by default this parameter is false. Docs read:
TRUE to return the transfer as a string of the return value of
curl_exec() instead of outputting it out directly.
EDIT
Setting CURLOPT_RETURNTRANSFER make curl_exec() return data, so it should be written manually, like this:
$url = "http://covers.stl-distribution.com/7819/lg-9781936417445.jpg";
$ch = curl_init($url);
$fp = fopen("./test.jpg", 'wb');
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch, CURLOPT_HEADER, 0);
fwrite($fp, curl_exec($ch));
curl_close($ch);
fclose($fp);
Also this code, that uses CURLOPT_FILE works for me just fine:
$url = "http://covers.stl-distribution.com/7819/lg-9781936417445.jpg";
$ch = curl_init($url);
$fp = fopen("./test.jpg", 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
fclose($fp);
so I basically suspect that your file handle is not valid, therefore cURL falls back to default output. Try this code with elementary error checking (you should ALWAYS check for errors):
$url = "http://covers.stl-distribution.com/7819/lg-9781936417445.jpg";
$fp = fopen("./test.jpg", 'wb');
if( $fp != null ) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
fclose($fp);
} else {
exit('ERROR: Failed to open file');
}
Note that my examples write to the same folder scripts sits in. It must work unless your server got file permissions messed badly. If it works for you, then investigate if (usually) user your scripts runs as can write to your target folder.
You haven't told your browser what type of file to expect, so it's probably defaulting to text/plain.
You need at least:
header('Content-type: image/jpeg');
As well, curl by default outputs whatever it fetches, unless you explicitly tell it you want to have the fetched data returned, or saved directly to file.

How to ensure download does not breaks using PHP Curl

I have using PHP's Curl function to download a list of pdfs from the backend. But sometimes some pdfs are corrupted.
I think, this happens because the downloads breaks and it will start to download the next pdf before completing the previous download.
Any idea how to prevent this? I am using the code below:
function downloadAndSave($urlS,$pathS)
{
$fp = fopen($pathS, 'w');
$ch = curl_init();
curl_setopt($ch,CURLOPT_PROXY,"http://test:1234");
curl_setopt($ch,CURLOPT_PROXYPORT,1234);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 0);
curl_setopt($ch,CURLOPT_URL,$urlS);
curl_setopt($ch, CURLOPT_FILE, $fp);
$data = curl_exec($ch);
fclose($fp);
}
I have tried using CURLOPT_CONNECTTIMEOUT but no difference. Any other way to prevent this?

Can I use a URL as the source for imagecreatefromjpeg() without enabling fopen wrappers?

I know it’s possible to use imagecreatefromjpeg(), imagecreatefrompng(), etc. with a URL as the ‘filename’ with fopen(), but I'm unable to enable the wrappers due to security issues. Is there a way to pass a URL to imagecreatefromX() without enabling them?
I’ve also tried using cURL, and that too is giving me problems:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.../image31.jpg"); //Actually complete URL to image
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
curl_close($ch);
$image = imagecreatefromstring($data);
var_dump($image);
imagepng($image);
imagedestroy($image);
You can download the file using cURL then pipe the result into imagecreatefromstring.
Example:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $imageurl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // good edit, thanks!
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); // also, this seems wise considering output is image.
$data = curl_exec($ch);
curl_close($ch);
$image = imagecreatefromstring($data);
You could even implement a cURL based stream wrapper for 'http' using stream_wrapper_register.
You could always download the image (e.g. with cURL) to a temporary file, and then load the image from that file.

use curl to download indirect image file

I am try to download image files from url from the following code, but it doesn't return the right content from the server. The image can be rendered in browser by loading the url or downloaded using curl in shell mode, but not in php execution. In php execution, the header's content type returned from the server is 'text/html' instead of 'image/jpeg' which it supposes to be.
Anyone has any ideas about this?
$url = 'http://count.koubei.com/showphone/showphone.php?f=jpg&w=104&h=10&bc=255,255,255&fc=0,0,0&fs=10&fn=arial&phone=LTIxMDM3MjIyOTc%3D%23dWBzmKEZpTh7YcWvOw%3D%3D';
$file_handler = fopen('phone.jpeg', 'w');
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_FILE, $file_handler);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_exec($curl);
curl_close($curl);
fclose($file_handler);
why not just use file_get_contents
like this
$img = file_get_contents("http://count.koubei.com/showphone/showphone.php?f=jpg&w=104&h=10&bc=255,255,255&fc=0,0,0&fs=10&fn=arial&phone=LTIxMDM3MjIyOTc%3D%23dWBzmKEZpTh7YcWvOw%3D%3D");
file_put_contents("photo.jpg",$img);

Categories