cURL upload files to remote server on MS Windows - php

When I use linux and try upload file to remote server using this script then all is well. But if i use Windows then script not working.
Script:
$url="http://site.com/upload.php";
$post=array('image'=>'#'.getcwd().'images/image.jpg');
$this->ch=curl_init();
curl_setopt($this->ch, CURLOPT_URL, $url);
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($this->ch, CURLOPT_TIMEOUT, 30);
curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($this->ch, CURLOPT_POST, 1);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post);
$body = curl_exec($this->ch);
echo $body; // << on Windows empty result
What am I doing wrong?
PHP 5.3
Windows 7 - not working, Ubuntu Linux 10.10 - working

If you are using Windows, your file path separator will be \ not the Linux style /.
One obvious thing to try is
$post=array('image'=>'#'.getcwd().'images\image.jpg');
And see if that works.
If you want to make your script portable so it will work on with Windows or Linux, you can use PHP's predefined constant DIRECTORY_SEPARATOR
$post=array('image'=>'#'.getcwd().'images' . DIRECTORY_SEPARATOR .'image.jpg');

Theoretically, your code should not work(i mean upload) in any, unix or windows. Consider this portion from your code:
'image'=>'#'.getcwd().'images/image.jpg'
In windows getcwd() returns F:\Work\temp
In Linux It returns /root/work/temp
So, your above code will compile like below:
Windows: 'image'=>'#F:\Work\tempimages/image.jpg'
Linux: 'image'=>'#/root/work/tempimages/image.jpg'
Since you mentioned it worked for you in linux, which means /root/work/tempimages/image.jpg somehow existed in your filesystem.
My PHP version:
Linux: PHP 5.1.6
Windows: PHP 5.3.2

You should try var_dump($body) to see what $body really contains. With the way you configured cURL, $body will contain either the response by the server or false, on failure. There is no way to differentiate between an empty response or false with echo. It's possible the request is going through just fine, and the server is just returning nothing.
However, as others have said, your file path seems invalid. getcwd() does not output a final / and you will need to add one to make the code work. Since you said it works on linux, even without the missing slash, I am wondering how it is finding your file.
I would suggest you create a path to the file relative to the PHP script that is running, or provide an absolute path and not rely on getcwd() which probably does not return what you are expecting. The value of getcwd() can be unpredictable across systems and is not very portable.
For example, if the file you are trying to POST resides in the same folder as your PHP script:
$post = array('image' => '#image.jpg'); is sufficient. If needed, provide an absolute path: $post = array('image' => '#/home/youruser/yourdomain/image.jpg');
As Terence said, if you need your code to be portable across Linux & Windows, consider using PHP's Predefined Constant DIRECTORY_SEPARATOR
$url = "http://yoursite.com/upload.php";
// images\image.jpg on Windows images/image.jpg on Linux
$post = array('image' => '#images'.DIRECTORY_SEPARATOR.'image.jpg');
$this->ch = curl_init();
curl_setopt($this->ch, CURLOPT_URL, $url);
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($this->ch, CURLOPT_TIMEOUT, 30);
curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($this->ch, CURLOPT_POST, 1);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post);
$body = curl_exec($this->ch);
var_dump($body);
getcwd() cURL

if working with xampp
Make sure that in php.ini configuration file
Line number 952 is uncommented
i.e
if line is
;extension=php_curl.dll
then make it
extension=php_curl.dll

I think, a better approach would be:
$imgpath = implode(DIRECTORY_SEPARATOR, array(getcwd(), 'images', 'image.jpg'));
$post = array('image'=>'#'.$imgpath);

Related

What is the cURL -T option in PHP

I'm trying to post to a file service with CDN translating the cli -T option to PHP code, but I don't really know what the equivalent is, or what is the corresponding code that would replicate it. I've seen a options around CURLOPT_HTTPHEADER, but that doesn't seem to work in correspondence to other headers.
The exact thing I'm trying to replicate is this:
curl -XPUT -T "test.png" -v -H "X-Auth-Token:MYTOKEN" -H"Content-Type: text/plain" "https://somecdn.com"
I think it's something like this, but I'm unsure:
$ch = curl_init();
// Set up the options
curl_setopt($ch, CURLOPT_URL, "https://mycdn.com/test.txt");
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"X-Auth-Token: mytoken",
"Content-type: text/plain"
)
);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, array("file" => "#test.txt") );
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
I'm surprised, I suppose, that -T flag doesn't have a similar curl_setopt.
So the precise question is this:
What is the proper way to replicate cURL CLI -T "test.png" in PHP?
Take into consideration as PHP 5.5 uploading file this way (#filename) is deprecated.
Also, PHP 5.5 introduces a new option/flag regarding upload process, called by CURLOPT_SAFE_UPLOAD:
TRUE to disable support for the # prefix for uploading files in
CURLOPT_POSTFIELDS, which means that values starting with # can be
safely passed as fields. CURLFile may be used for uploads instead.
Added in PHP 5.5.0 with FALSE as the default value. PHP 5.6.0 changes
the default value to TRUE.
So if you've PHP 5.5+ you must set CURLOPT_SAFE_UPLOAD (though 5.5 is false by default) to false:
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
Another option is using the CURLFile class.
And remember: Filename MUST be absolute path.

How to fetch the url content using php curl or file_get_content on the same server?

I have some code to convert a PHP page to HTML:
$dynamic = "http://website.net/home.php";
$out = "home.html" ;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"$dynamic");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$file = curl_exec($ch);
file_put_contents($out, $file);
This works perfect in localhost but it takes too much time/doesn't work on the live site.
I've tried php_get_contents, but that also doesn't work.
Note:
http://website.net/home.php page is in the same site where the code is hosted.
curl is enabled and allow_url_fopen is on as per phpinfo() in both localhost and at server.
EDIT:
It works fine when using other website's page instead of my website.
The site's target page perfectly loads in my browser.
The web page of my website is loading fast as usual but when I use curl or file_get_contents, it's too slow and even can't get output.
I think you have DNS resolving problem.
There is two ways you can use your website's locahost instead of the external domain name.
1. If you have your own server / VPS / Dedicated server,
Add entry in vim /etc/hosts for 127.0.0.1 website.net or try to fetch the content with localhost(127.0.0.1).
2. If you are using shared hosting, then try to use below url(s) in your code,
http://localhost.mywebsite.net/~username/home.php.
OR
Try to call http://localhost.mywebsite.net/home.php
Try this to fetch the url content -
$dynamic = TRY_ABOVE_URL(S)
$out = "home.html" ;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$dynamic);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$file = curl_exec($ch);
if($file === false) {
echo 'Curl error: ' . curl_error($ch);
}
file_put_contents($out, $file);
To investigate the reason why is it not working on live server, Try this:
$dynamic = "http://website.net/home.php";
$out = "home.html" ;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $dynamic);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$file = curl_exec($ch);
if($file === false)
{
echo 'Curl error: ' . curl_error($ch);
}
curl_close($ch);
file_put_contents($out, $file);
I think it depends on the provider SSL configuration.
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSLVERSION, 3);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
Check for know smth. about SSL configuration of your provider.
Looks like it is a network routing issue, basically the server can't find a route to website.net(itself). This has is a server issue and not a PHP issue. The quickest solution is to edit the hosts file on the server and set website.net to 127.0.0.1.
On linux servers you will need to add the following line to the bottom of /etc/hosts to:
127.0.0.1 website.net
Alternatively you can try fetching http://127.0.0.1/home.php but that will not work if you have multiple virtual hosts on the server.
Try this one:
file_put_contents("home.html", fopen("http://website.net/home.php", 'r'));
but curl should work as well. If you have SSH access to the server, try to resolve your domain name using ping or something. It is possible to have a local DNS issue - it will explain why you can download from external domains.
For my example, you'll need allow_fopen_url to be On, so please verify that by phpinfo() first.

cURL PHP not working if CURLOPT_RETURNTRANSFER set true

I try to extract the HTML of a site via cURL for PHP. Normally it works fine, but there are some website the response is empty. For example if I execute the following script for the URL alditalk.de:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.alditalk.de/');
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/4");
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
$data = curl_exec($ch);
curl_close($ch);
In this case the variable $data is empty. The strange thing about that is if I change curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); to curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); the website will be printed on the screen. The problem is, I need the content in a variable for further operations.
I tried it locally on WAMPP as well on my Hoster. I also tried to set some header information without success. There are also no errors. Are there any solutions?
Its working for me. i think you are not enable the curl extension.
Since you're using XAMPP, uncomment the line
;extension=php_curl.dll
in xampp\apache\bin\php.ini, and then restart the Apache service.
NB: In newer XAMPP versions, PHP has moved to root xampp folder xampp\php\php.ini.
Steps in WAMP SERVER
The steps are as follows :
Close WAMP (if running)
Navigate to WAMP\bin\php\(your version of php)\
Edit php.ini
Search for curl, uncomment extension=php_curl.dll
Navigate to WAMP\bin\Apache\(your version of apache)\bin\
Edit php.ini
Search for curl, uncomment extension=php_curl.dll
Save both
Restart WAMP
Its working fine for me ..I think the curl extension is not enabled well ..Are you using xampp ??
Go to http://www.anindya.com/php-5-4-3-and-php-5-3-13-x64-64-bit-for-windows/
and download the curl version that is same as your php version..
This doesn't directly answer your question, but it offers a bit of a workaround: Could you consider using ob_start() and associated functions to capture the output that you are able to get?
The idea above is a hacky way to solve it, of course. Before falling back on ob_start(), I would suggest double-checking all variable names, ini settings, etc., since it's always possible that you're doing something like accidentally trying to access the contents of $daya rather than $data -- which is precisely the kind of typo I just spent 45 minutes on in my own script. Fixing my variable name fixed the the misbehavior that had originally led me to this question.
Hoping that helps somebody. Cheers!

PHP - Display cURL Verbose info

I'm having some trouble with a particular cURL command and I'd like to see the headers and responses. In the command line I use -v and it displays everything, however...
In PHP I'm attempting to use:
curl_setopt($curl, CURLOPT_VERBOSE, 1);
However, nothing is being displayed.
I'm using PHP 5.3.24 on Windows Server 2008 on IIS.
Supposedly the info is sent into the stderr stream which I assume means the regular log used for PHP errors - however nothing is going there either. I'm getting no header results for cURL commands that I know are working and those that I know are not working.
My guess is that you need to also return the buffer. This code works under Linux and might work for you under Win2008:
$browser = curl_init();
curl_setopt($browser, CURLOPT_URL, $url);
curl_setopt($browser, CURLOPT_RETURNTRANSFER, true);
curl_setopt($browser, CURLOPT_VERBOSE, true);
$data = curl_exec($browser);
echo $data;

Accessing files on external server

Is there any way to access files of Third party server using PHP?
Yes. You just fopen them if url_fopen is enabled, or use CURL.
The easiest way - assuming url_fopen_wrappers are enabled - is simply using file_get_contents() with a remote (http://, ftp://) URL.
If you don't want to rely on them being enabled, use CURL - while it requires a PHP extension it's pretty common so chances are high it's enabled even on shared hosting.
Here are examples for both methods:
// using url_fopen_wrappers
$contents = file_get_contents('http://stackoverflow.com');
// using CURL
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://stackoverflow.com');
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$contents = curl_exec($curl);
curl_close($curl);
you could even use copy('thirdPartyFileUrl', 'fileO')

Categories