How to send form fields and a file using PHP Curl? - php

I'm trying to send form fields and file to a web service using php curl. The form has already been passed from a browser to a proxy php client web app and I'm trying to forward it to the web service.
When I pass an array to curl_setopt like this:
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $this->fields);
I get a Array to String notice although it is meant to take an array. Here's my array that is passed to $this->fields in the constructor.
$fields = array('title'=>$title,
'content'=>$content,
'category'=>$category,
'attachment'=>$_FILES['attachment']);
If I pass a string using http_build_query my web serivce complains about not having multipart/form data.
If I then force the multipart/form enctype using curl_setopt I get an error saying there's no boundary:
org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
Any ideas?

The array to string notice you have with the following code :
$fields = array(
'title'=>$title,
'content'=>$content,
'category'=>$category,
'attachment'=>$_FILES['attachment']
);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $fields);
is not because of you're passing an array as 3rd parameter to curl_setopt : it's because you're passing an array for attachment.
If you want to pass a file this way, you should pass its absolute path, pre-pending a # before it :
$fields = array(
'title'=>$title,
'content'=>$content,
'category'=>$category,
'attachment'=> '#' . $_FILES['attachment']
);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $fields);
(This is supposing that $_FILES['attachment'] contains the full path to your file -- up to you to change this code so it's using the right data, if needed)
As a reference, quoting the manual page of curl_setopt, for the CURLOPT_POSTFIELDS option :
The full data to post in a HTTP "POST" operation.
To post a file, prepend a filename with # and use the full path.
This can either be passed as a urlencoded string like 'para1=val1&para2=val2&...' or as an array with the field name as key and field data as value.
If value is an array, the Content-Type header will be set to multipart/form-data.

try this,
$filePath = "abc\\xyz.txt";
$postParams["uploadfile"] = "#" . $filePath;
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_URL, 'https://website_address');
curl_setopt($ch, CURLOPT_POST, 1 );
curl_setopt($ch, CURLOPT_POSTFIELDS, $postParams);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
if (curl_errno($ch))
{
echo curl_error($ch);
exit();
}
curl_close($ch);

Related

Php Curl send File with data

I need to upload 3 files along with variables in post data. This is what my call looks like -
$data['type1'] = new CurlFile($file1);
$data['type2'] = new CurlFile($file2);
$data['type3'] = new CurlFile($file3);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data, "var1: $val1", "var2: $val2");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data', "headkey: $headkeyValue"));
I am not able to get $app->request()->post('var1'); from slim framework. It is empty.
I am able to get the headkey from the Header as $app->request()->headers('headkey');
I am able to get the data in $_FILES
Here the sample curl request
$curlFile = curl_file_create($uploaded_file_name_with_full_path);
$post = array('val1' => 'value','val2' => 'value','file_contents'=> $curlFile );
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$your_url);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$result=curl_exec ($ch);
curl_close ($ch);
Don't forget to put the appropriate header.
You can also find good source here
Curl File Upload
to send file via CURL. Make sure that you are passing your file on file_contents key in above code.
It's due to the fact that all files uploaded with HTTP POST method are in $_FILES global variable. That's why you cannot access files by this way
$app->request()->post('val1');
but you can by using $_FILES
$_FILES description
An associative array of items uploaded to the current script via the HTTP POST method. The structure of this array is outlined in the POST method uploads section.
This is what I did in alignment to ssingh's answer:
$data['type1'] = new CurlFile($file1);
$data['type2'] = new CurlFile($file2);
$data['type3'] = new CurlFile($file3);
//New Code Added
$data['var1'] = "$val1";
$data['var2'] = "$val2";
//removed the trailing string
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

PHP - How to get POSTFIELDS sent with CURL?

I am using curl to call API method (Symfony2, FOSRestBundle) and wonder how can I get the data sent in POSTFIELDS?
$_params = [];
$data_string = json_encode($_params);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $_method);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($curl, CURLOPT_VERBOSE, true);
$json = curl_exec($curl);
If I send something in for example CURLOPT_HTTPHEADER I can get it later in controller using
$request->headers->get("some_variable");
But how can I access $data_string? I have dumped almost every possible variable and still nothing.
To retrieve a POST value in symphony you can use:
$request->request->get('key', 'default value');
Assuming $_params is a valid json object, you need to url-ify the data for the POST, i.e.:
$post_fields = http_build_query(json_decode($_params));
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_fields); </s>
To retrieve all post values in symphony you can use:
$params = $this->getRequest()->request->all();
$params['val1'];
$params['val2'];
As I understand your first code snippet, you're effectively trying to POST a JSON string? It was my understanding that your PHP code wouldn't work as per the PHP documentation for CURLOPT_POSTFIELDS:
This parameter can either be passed as a urlencoded string like 'para1=val1&para2=val2&...' or as an array with the field name as key and field data as value.
But as per this blog post apparently you can do it your way.
Anyway, back to your question. To get the full content of a request, you would do:
$content = $request->getContent();
And to then decode the JSON you would do:
$params = json_decode($content);
Another StackOverflow answer covers this. About the only thing I'd say is that you need to correctly set the MIME type when you're sending the post, e.g.
curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json' ]);
The previously mentioned blog post covers this.

How to use an array in an API using curl

I am trying to access the cdnify API to purge cache for an individual file ( https://cdnify.com/learn/api#purgecache )
This is my current code
$cdn_api_user = env('CDNIFY_API');
$cdn_api_password = env('CDNIFY_API_PASS');
$cdn_api_resource = env('CDNIFY_API_RESOURCE');
$cdnifyapicacheurl = 'https://' . $cdn_api_user . ':' . $cdn_api_password . '#' . 'cdnify.com/api/v1/resources/' . $cdn_api_resource . '/cache';
return print $cdnifyapicacheurl;
$fields = array(
'files' => $storageFilename
);
$fields_string = http_build_query($fields);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $cdnifyapicacheurl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
//unless you have installed root CAs you can't verify the remote server's certificate. Disable checking if this is suitable for your application
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//perform the HTTP DELETE
$result = curl_exec($ch);
//close connection
curl_close($ch);
the env variables at the top call in my api key, password, and resource for the url. I have verified I am logging in via that url.
When I debug through my code i get an error on
$fields = array(
'files' => $storageFilename
);
which is Array to string conversion.
The $storageFilename variable returns
$storageFilename = "/" . $directoryname . "/" . $asset->name;
which is the filename required for the API call of DELETE.
I can't get passed that $fields array. The other stuff below it may or may not run properly. I am just stuck on how to write this part out.
CURLOPT_POST is just there to indicate if some post data should be included in the HTTP request, so its value should a boolean (true or false).
If your array $fields represents the data to be posted, you need to use http_build_query() to assign them to CURLOPT_POSTFIELDS:
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
There is a return in your code that stops the code the curl code is not getting executed remove it or comment it using // and try again and CURLOPT_POST value is boolean true or false that indicates if you want to use post method or not, your CURL code is really messed up you want to use http delete method or post method ?? You can only use one method, please learn how to use php cURL first http://php.net/manual/en/book.curl.php

PHP cURL: circumventing '#' denoting a file POST

I'm trying to make a cURL post, and one of the parameters includes a string prefixed with the '#' symbol. Typically for a cURL post, the '#' means I'm trying post a file, but in this case, I just want to pass the string prefixed with '#'. Is there a way, or what is the best way to get around this?
Here's my params array:
$params = array(
'UserID' => $this->username,
'Password' => $this->password,
'Type' => $type,
'Symbol' => $symbol, // this will look something like #CH14
'Market' => '',
'Vendor' => '',
'Format' => 'JSN'
);
And here's how my cURL post is taking place (the url is irrelevant to the actual problem.):
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
// Return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
if($response === FALSE)
{
$error = curl_error($ch);
$error_code = curl_errno($ch);
throw new Exception("CURL ERROR: #$error_code\n$error\n");
}
curl_close($ch);
return $response;
This works for everything I need it to do except when I need to pass it a symbol with an '#' in front. Any help would be greatly appreciated. Thanks.
According to the curl_setopt() manual entry:
CURLOPT_POSTFIELDS
The full data to post in a HTTP "POST" operation. To post a file, prepend a filename with # and use the full path. The filetype can be explicitly specified by following the filename with the type in the format ';type=mimetype'. This parameter can either be passed as a urlencoded string like 'para1=val1&para2=val2&...' or as an array with the field name as key and field data as value. If value is an array, the Content-Type header will be set to multipart/form-data. As of PHP 5.2.0, value must be an array if files are passed to this option with the # prefix. As of PHP 5.5.0, the # prefix is deprecated and files can be sent using CURLFile.
Hence, we can simply convert it to a string using http_build_query():
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
Use http_build_query() to build the query string.
From the documentation for the function:
Generates a URL-encoded query string from the associative (or indexed) array provided.
As stated above, it will correctly encode all the special characters as required. It can be used as below:
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
Online demo

PHP & CURL not sending file, even with # prepended

I am using PHP (WAMPServer) to receive a form submission, and then CURL to pass the file to another server for processing.
Here is an example to illustrate (not the actual code):
$data = array(
'file' => '#'.$_FILES['key']['tmp_name']
);
Here's what I'm using for CURL... and as I was pasting the code I noticed that I still have http_build_query() in my code... so, that must be the problem.
$CURL = curl_init();
curl_setopt($CURL, CURLOPT_URL, $operation['callback']);
$query_string = http_build_query($arguments);
curl_setopt($CURL, CURLOPT_POSTFIELDS, $query_string);
curl_setopt($CURL, CURLOPT_POST, TRUE);
curl_setopt($CURL, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($CURL);
curl_close($CURL);
return $result;
My problem is that the last server isn't receiving the file. Instead, the data is passed as a key-value pair.
$_POST contains 'file' => '#c:\wamp\tmp\xyz.tmp'
What I would prefer, is that the files was transferred, and $_FILES has information about it.
Don't build an http query for the CURLOPT_POSTFIELDS. Curl can directly accept an array of fields and do its own encoding/mangling.
By building your own query, you're 'hiding' the # that indicates a file upload and CURL will not trigger its upload mechanisms.
In other words, this will fix things:
$data = array(
'file' => '#'.$_FILES['key']['tmp_name']
);
curl_setopt($CURL, CURLOPT_POSTFIELDS, $data);
if you add your CURL method code, we could better answer you...
Try to transfer the file as binary, and add the filesize in the header in your curl.

Categories