I use this cmd to successfully download result.csv
curl.exe https://example.com/rest -u "xx:yy" -F [email protected] > result.csv
I want to do this using PHP. But no avail…
Help please.
This is my PHP:
$url = 'https://example.com/rest';
$xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request xmlns="http://example.com"><search path="report_date" value="2023-07-01T00:00:00+0000"/>'; //and so on..
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERPWD, 'xx:yy');
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, "xmlRequest=$xml");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
var_dump($data); //just to check if it has requested data (will save to file later)
if(curl_errno($ch))
print curl_error($ch);
else
curl_close($ch);
It does not have requested data. But it gives this
string(346) "
500
An error has occured.
Please try again and if the problem persists, contact us.
"
2
Answers
if your php code has it as a string, not a file, then you first have to put it in a file (because PHP’s libcurl api does not (yet?) support uploading files in
multipart/form-data
from strings), to get around this limitation you can do something likethen change your code to
also you need to remove this:
in
multipart/form-data
-requests, the Content-Type is supposed to be something likeContent-Type: multipart/form-data; boundary=------------------------e74d6203325745a2
but libcurl generate this header for you automatically, and you risk corrupting the POST request, making it invalid and un-parsable, if you change the outer Content-Type yourself.
Fix those 2 things and your code should work.
Meanwhile your file.xml will have it’s own "inner" Content-Type, here is a full sample with both the outer and inner Content-Type:
curl_setopt($ch, CURLOPT_HTTPHEADER
-call was the outer Content-Type (the wrong one)(Some variation of this question has been asked many times before, but I can’t find a duplicate right now, strange)
What you can say as a rule of thumb is that you look for each curl(1) command line option (+ argument) and operand and find the appropriate curl_setopt($option, $value).
So you can compare the command-line against the PHP code to locate potential issues that may cause the 500 error. Otherwise you can’t find out what is wrong in the PHP code while the command-line works.
So let’s take a look what we’ve got here in that command-line:
https://example.com/rest
(URL
)-u "xx:yy"
(<user:password>
)-F [email protected]
(<name=content>
)Then lets see which curl_setopt() operations there are in the PHP code:
curl_setopt($ch, CURLOPT_USERPWD, 'xx:yy');
– OK, matches 2.) above.curl_setopt($ch, CURLOPT_URL,$url);
– OK, matches 1.) above.curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
– OK, your config.curl_setopt($ch, CURLOPT_TIMEOUT, 10);
– OK, your config.curl_setopt($ch, CURLOPT_POST, true);
– OK, mirrors the POST method matching 3.) above.curl_setopt($ch, CURLOPT_POSTFIELDS, "xmlRequest=$xml");
– NOT OK, does not match 3.) above. 3.) above does a file-upload, here you’re setting a form string value. This is not a file-upload.I can imagine this could trigger a 500 on the remote side, as they have little error handling and the process just crashes.
You perhaps want to create a file-upload from the string so that the data of the file-upload is the string contents.
If that is the case, this is how it works in PHP curl tailored to your
-F [email protected]
curl(1) option and argument example:Cf. CURLStringFile; answer to Send string as a file using curl and php and curl_setopt(CURLOPT_POSTFIELDS) (it already mentions CURLStringFile).
let’s continue with the next lines:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
– NOT OK, the original curl command line does not have it. Remove it.curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
– NOT OK, the original curl command line does not have it. Remove it.curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
– NOT OK, the original curl command line does not have it. Remove it.curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
– NOT OK, the original curl command line does not have it. Remove it.As you have already written, you’re not yet interested in converting the redirect to file (the
> result.csv
at the end of the command-line), so this should already be it.