How to send a file with curl without using a form? - php

I am working on a project where I use two separate servers, one for the development and one for the visible version. This is how the process works, and where I'm having troubles: Every morning, I run some VBA macros that collects data, compiles that data (mainly .xlsx files) and sends it to my development server via FTP. The visible server is supposed to use that data to display some informations etc, but FTP is blocked on that server.
Because of that, I have to copy everything from my development server to the visible server every morning, so that the data on the visible server is updated, and I'd like to automatize that.
I tried sending the data from the VBA macros directly to the visible server via HTTP Requests (WinHTTPRequest to be exact) but that didn't work.
I searched online and found that cURL can send HTTP requests through PHP, and i'd like to use that solution if possible, here is my current code:
send.php:
<?php
$request = curl_init('mysite/receive.php');
curl_setopt($request, CURLOPT_POST, true);
curl_setopt($request,
CURLOPT_POSTFIELDS,
array(
'file' => '#MyFileRealPath.xlsx;filename=file'
));
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
echo curl_exec($request);
curl_close($request);
?>
receive.php:
<?php
var_dump($_FILES);
?>
When I run send.php, I get:
array(0) { }
So the receive.php file does not get any file, does someone know how to fix that?
If what I'm trying to do is not possible, does someone know any other way that I could try to send the files from the development server to the visible one?
Thanks and sorry for my not perfect english, I'm not a native speaker.
Have a nice day!

I had something similar today when our server suddenly did not send a file over curl anymore.
I found that the PHP version was upgraded.
Apparently, in a previous version a new curl setting (CURLOPT_SAFE_UPLOAD) was introduced which disables using # symbol for file uploads, and "PHP 5.6.0 changes the default value to TRUE".
I think you need to add this setting using curl_setopt and disable it, like:
$request = curl_init('mysite/receive.php');
curl_setopt($request, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
curl_setopt($request,
CURLOPT_POSTFIELDS,
array(
'file' => '#MyFileRealPath.xlsx;filename=file'
));
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
Alternatively, you can use CurlFile:
$request = curl_init('mysite/receive.php');
curl_setopt($request, CURLOPT_POST, true);
curl_setopt($request,
CURLOPT_POSTFIELDS,
array(
'file' => new CurlFile('MyFileRealPath.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
));

Related

PHP + cURL gets file that shouldn't exist

This is my first question on here and I wouldn't ask if I haven't tried nearly everything in my might already. My problem is as follows:
I got tasked to maintain an old webapp in our company and part of it was to change an old date in a html file to the current year. I did that and when I access the file with the required parameters directly it works. Now the app itself doesn't access this file directly but loads it in through something they called "proxy.php" - it defines allowed hosts and some other stuff but the thing it mostly does is get data via cURL. If I access the file that I changed through the "proxy.php" it returns a file that shouldn't exist anywhere on the server (with old content in it).
I replicated proxy.php's function down below with the same result (an old file is served):
<?php
//phpinfo();
//Proxy.php test because weird things are happening...
$url = $_GET["url"]; //The url that it gets is escaped already.
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPGET,1);
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
$xml = curl_exec ($ch);
echo $xml;
?>
I also got told by a colleague that they always only altered they date in the html file and it worked until now. I hope I provided enough information about my problem. Thank you in advance.
Just wanted to give a quick update as I have resolved the issue thankfully.
Deep in the configuration was an old proxy server that seemed to be serving cached files.
I changed the "proxy.php" to use a new proxy server:
$proxy = "your.proxy.server:port";
curl_setopt($ch, CURLOPT_PROXY, $proxy);
Thanks everyone for your advice :)

php cURL post data to remote server not working

I'm trying to send data via cURL post but I've never tried it before and I don't know if I'm doing it right.
What I want to do is sent a file via post to a file from my remote server and there read the file and insert data into database but unfortunately it's not working and error_log doesn't show me anything.
My code looks like this:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://".$host."/file.php");
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
'file' => '#'.realpath(../path/to/file/'.$_POST['file_name'].'.txt'),
'action' => 'first',
'check' => $_POST['file_name'],
));
$result = curl_exec($ch);
curl_close($ch);
This code is placed after some sql querys and code made to write this sql results into the file that I'm trying to send.
Here is the Answer by Shakir Khan you Should follow:
PHP: upload file from one server to another server - Stack Overflow
OR you should read PHP Documentation carefully there is a huge amount of CONSTANT availabe to use: curl_setopt

Post file content using CURL

How can I "correctly" upload the content of a file with cURL?
There are a lot of explanations and questions here where tmp files are send by curl with a #prefix on the file or using the curlFile api. In My use case I don't want to create a tmp file, and just post the content of file_get_contents('php://input') as body of the post request. The server does not accept multipart form requests.
The Following snipped will work in PHP7:
$body = file_get_contents('php://input');
$ch = curl_init();
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
It feels ugly to set the content type to json, no matter what the actual content of the stream may holds. But it seems to work. Sadly I need to support a really old version of PHP and feel like running out of options.
My question is:
Is the above example correct, even for PHP 7 or can it be made better?
Additionally: Is there any improvement or option that can be used to make this work with PHP 5.3.10? In this old version the post body always seems to be empty.
Finally I found and answer on this blog
Adding curl_setopt($curl, CURLOPT_POSTREDIR, 3); was the required option to acutally make the post request work without having an empty body.
Edit & heads up: This option is only needed when you expect your request to be redirected. I made a mistake while asking this question and posting the answer. Please check if your requests is redirected form http to https or the other way around and fix this first to prevent problems.
Copied from blog post of Evert Pot, linked above:
Using CURLOPT_POSTFIELDS you can supply a request body as a string.
Lets try to upload our earlier failed request using that method:
<?php
$curl = curl_init('http://example.org/someredirect');
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl, CURLOPT_POSTFIELDS, file_get_contents('largefile.json'));
curl_exec($curl);
?>
This also will not work exactly as you expect. While the second
request to /someredirect will still be a POST request, it will be sent
with an empty request body.
To fix this, use the undocumented CURLOPT_POSTREDIR option.
<?php
$curl = curl_init('http://example.org/someredirect');
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl, CURLOPT_POSTFIELDS, file_get_contents('largefile.json'));
curl_setopt($curl, CURLOPT_POSTREDIR, 3);
curl_exec($curl);
?>
According to the PHP changelog, this was added in PHP 5.3.2, and
according to PHP bug #49571 there are four possible values:
0 -> do not set any behavior 1 -> follow redirect with the same type
of request only for 301 redirects. 2 -> follow redirect with the same
type of request only for 302 redirects. 3 -> follow redirect with the
same type of request both for 301 and 302 redirects.

cURL request getting wrong request version in Google App Engine

I have a cURL request in my code which works fine when running locally:
$url = "http://ipinfo.io/{$_SERVER['REMOTE_ADDR']}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$locale = json_decode($response);
and returns a JSON as expected. Our production system is on Google App Engine, however, where I get the website version for a browser rather than the JSON.
I can get this cURL request to work if I change
google_app_engine.enable_curl_lite = "1"
in the php.ini in the root directory of my project to
extension = "curl.so"
but Google's documentation insists the former is to be used on production. Additionally, using the latter breaks things like Monolog's SlackHandler.
Is there a way to get the JSON from this cURL request while still using Google's "cURL Lite"?
From the ipinfo.io documentation:
"We do a little bit of magic on the server to determine if we should send the JSON response or the webpage. We usually get it right, but if you're seeing the webpage instead of the JSON (or want to check the JSON output in a browser) you can force the JSON response by adding /json to the end of the URL"
Adding /json to the end of the URL worked for me in this case, but I wanted a more general solution. Since Google's cURL Lite uses their URL Fetch in the background, ipinfo.io's "magic" is somehow getting confused. I found that by specifying the Accept header then the /json addition wasn't required. In PHP:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json'));
Thanks to the folks on the #php channel of NashDev Slack for helping me on this one!

Is fopen safe to use in public software?

I am creating a web application that I hope to release to the public for downloading and installing on anyone's own web server, however I just was informed that some webhosts disable the use of fopen in php due to "security issues", particularly on shared hosts. I use fopen during the installation process of the application, should I be concerned about this? Is this a common practice in shared hosts? If so, is there another way I can write to a file? I have heard of cURL, but this would require more advanced knowledge on the part of the end user, no? If so, this can obviously not be expected. Thanks very much!
fopen() is never disabled. The php.ini setting "allow_url_fopen" however is. So if you only access local files, not http:// URLs via fopen() this is not really a concern.
If you need URL support you should otherwise include a HTTP request class, like the one in PEAR. This way you avoid the user-unfriendly dependency on the cURL extension module.
In my limited experience, fopen() is seldom disabled. Writing to a local file with curl is nonsense, so this wouldn't be an alternative. As all writing to a local file kind of depends on fopen, the most usual route for normal packages is:
Trying to set the content in a file on installation (possibly a file already there with a decent default in the normal packages files).
On failure, present to user with the content you'd like to set, and offer him the option to either copy/paste that content manually, or to retry to set the content (for instance, when the user sets the file permissions correctly, which you of course explain how to do).
using cURL:
function GET($url,$header = null,$post = 0,$cookie = null){
$handle = curl_init();
curl_setopt($handle, CURLOPT_URL, $url);
curl_setopt($handle, CURLOPT_HEADER, $header);
curl_setopt($handle, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
if($post) {
curl_setopt($handle, CURLOPT_POST, true);
curl_setopt($handle, CURLOPT_CUSTOMREQUEST,($post)?"POST":"GET");
curl_setopt($handle, CURLOPT_POSTFIELDS, $post);
}
curl_setopt($handle, CURLOPT_COOKIE, $cookie);
if(preg_match('/https/',$url)) {
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
}
return($buffer = #curl_exec($handle)) ? $buffer : 0;
}
//A basic example of the requisition process :
echo GET('http://google.com',1)
//post data:
GET('/test.php',1,
array('Name' => 'Jet',
'id' => 12,
'foo' => 'abc'));
returns:
successfully : source-code;
0 : Request failed
//send cookies :
GET('http://example.com/send.php',1,
array('Name' => 'Jet',
'id' => 12,
'foo' => 'abc'),"cookies");
file_put_contents :
http://php.net/file_put_contents

Categories