Upload image from client web application to RESTful API - php

I've been working on building an API as a learning purpose. It is essentially a twitter-like micro post API. Alongside the API I've been building a client web application powered off of the API. I am able to successfully post statuses without any problems. But now I am trying to allow users to upload an image along with the post. The client application is built using the mvc pattern. I post the submitted post to my post controller via jQuery ajax like so:
$.ajax({
url: '../../posts/newPost',
type: 'POST',
data: formData,
async: true,
success: function (data) {
console.log(data);
$('#post-form-area').removeClass('loading');
$('#post-body').val('');
$('#files').val('');
$('#attached').find('img').remove();
$('#attached').hide();
},
cache: false,
contentType: false,
processData: false
});
I am able to successfully get the file data using the $_FILES array within my controller. However, I am having a lot of difficulty figuring out how to send this to my RESTful API. I created a class to handle my API calls and here is the code for my POST method:
$ds = json_encode($params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $ds);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//execute the request
$result = curl_exec($ch);
Here is the data that I pass to post a text only status:
$data = array('user_id' => $_SESSION['user_id'], 'body' => $body, 'time' => $timestamp);
I have tried passing $_FILES['file']['tmp_name'] as part of the array, but on API side the $_FILES array is null. I tried following this example, but I ran in to the same problem.
The way my API is set up, if the $_SERVER['request_method'] is POST I get the contents from cURL from php://input and then pass these parameters to the necessary controller. Do I need to add anything here that will give me access to the $_FILES array? I've been digging for about 3 hours now and haven't been able to find anything that has helped me, so I appreciate any help.
Thanks!
Edit:
I don't see how this is a duplicate as the link you posted that it is a duplicate of has nothing to do with uploading an image through a RESTful service...
Edit 2:
I've narrowed it down to how I am sending the data from my client application because I am successfully able to use the following command line code to upload a file:
curl -X POST -F "image=#test.JPG" http://rest.mattaltepeter.com/posts/upload
And then the code to receive it:
public function uploadAction() {
$result['success'] = move_uploaded_file($_FILES['image']['tmp_name'], SITE_ROOT . '/uploads/' . $_FILES['image']['name']);
$result['data'] = UPLOAD_DIR . $_FILES['image']['name'];
return $result;
}
I came across this tutorial and have been able to implement it fine with a static URL to an image, but that isn't very helpful as I want a user to be able to select their own image to upload with their post. So it looks like my issue is revolved around getting the full path as that tutorial mentions on line 4 of the first code block and sending it to the api. So how do I get that same information from the $_FILES array instead of a static file URL?

Finally figured it out. It had to do with using json_encode() to send my POST data. As soon as I tried it with out json_encode(), I had access to the $_FILES array. I think I'll have to add a parameter to my ApiCall->post() method to tell it if I want to json_encode() the data I wish to pass.

Related

WordPress using AJAX connections to third-party server

I'm okay with WordPress and editing files but I've had to take over a website from the designers and I'm a bit stuck.
What they've done is create an AJAX file that is used for all website submitted forms, and all of those forms are redirected to their own servers, before being sent on to the customer.
Obviously this is not ideal for a variety of reasons, but I'm unsure how to fix it. There is a rule for each form/contact method, then a final rule at the bottom of the file that I presume applies to all the previous rules.
This is:
function postThis($data_to_post) {
$form_url = "https://abcdef.co.uk/__mailer/__send123456.php";
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL, $form_url);
curl_setopt($curl,CURLOPT_POST, sizeof($data_to_post));
curl_setopt($curl,CURLOPT_POSTFIELDS, $data_to_post);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
$result = curl_exec($curl);
curl_close($curl);
return $result;
}
I'm not sure how to replace the https (which I've changed the URL of) bit with something that will simply send the forms from the website to the website owners email address, without the intercept.
You could set up individual jquery functions that are returned on form submit to point to a php email function.
Form:
<form onsubmit="return someFunction();">
</form>
Javascript:
function someFunction(){
var data = $('form').serialize();
$.ajax({
url: phpMailClass.php,
data: data,
method: 'post',
success: function(resp){
// Handle the response upon success
}
});
}
Receive the user inputs in a php file then use PHP's mail() function to send the form(s) to the desired recipients.

PHP: How to send cookies with REST API call by clicking on a link?

I'm new to the REST APIs style of web development. I have to send 2 cookies along with 1 REST API. How do I send them together by clicking on a link?
For example, if an user clicks on the link, it is supposed to make the REST API call and send the cookie along with it. I know how to do it in the cURL but I am confused as to how I can trigger that via a link. Ideally, the user should be able to download a zip file by clicking the link. The link should call the REST API and send 2 cookies over to get the zip file. I am able to get the raw code of the zip file using the following code but is not able to achieve that by clicking on the link.
$getResultsDetails = curl_init();
$getResults_service_url = '<URL of the REST API call>';
curl_setopt($getResultsDetails,CURLOPT_URL,$getResults_service_url);
curl_setopt($getResultsDetails,CURLOPT_COOKIE,"LWSSO_COOKIE_KEY=".$LWSSO_COOKIE_KEY.";QCSession=".$QCSession);
curl_setopt($getResultsDetails, CURLOPT_RETURNTRANSFER, true); //get response
$getResults_service_url_response = curl_exec($getResultsDetails);
curl_setopt($getResultsDetails, CURLOPT_RETURNTRANSFER, true);
if ($getResults_service_url_response === false) {
$info = curl_getinfo($getResultsDetails);
curl_close($getResultsDetails);
die('error occured during curl exec. Additional info: ' . var_export($info));
}
curl_close($getResultsDetails);
Any ideas how I can achieve that?
This is mostly a duplicate of this but with the added 'how do I?' part. So, heres the bit to add to the answer of that question.
just use a link to direct your user to the php script making the call.
you can do this in 2 ways:
1.
click me
read this answer for details on how to do the cookie part.
or
2. use an ajax call using jquery:
from jquery docs
$.ajax({
type: "POST",
url: "path/to/yourCurlScript.php",
data: data,
success: success,
dataType: dataType
});
same script is called, so process cookies in the same way.
for the best user experience I would probably opt for number 2. I dont know what it is that youre planning on retrieving from the API, but you can pipe it into a file using either.

Laravel 4 make post request from controller to external url with data

I am looking for a way to make a post request from a controller to an external url. The data being posted is a php array. The url to recieve is an ecommerce API in an external url. The post has to be done from the controller method. The url should reply with 'success', 'error', 'failure' or 'trylater' string. I have tried the following with no success:
return Redirect::to("https://backoffice.host.iveri.com/Lite/Transactions/New/Authorise.aspx", compact($array));
I have tried curl too:
$url = 'https://backoffice.host.iveri.com/Lite/Transactions/New/Authorise.aspx';
//url-ify the data for the POST
$fields_string ='';
foreach($array as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'& ');
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($array));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
Part of the array being sent is the callbacks that the API uses to responds:
'Lite_Website_Successful_url' => 'https://mydomain.com/order/'.$order_id,
'Lite_Website_Fail_url' => 'https://mydomain.com/checkout/fail',
'Lite_Website_TryLater_url' => 'https://mydomain.com/checkout/trylater',
'Lite_Website_Error_url' => 'https://mydomain.com/checkout/error'
Please let me know how to do a POST request properly with data carried with it to an external url. An ajax post from the controller too would help but I have tried with no success. But I would prefer a laravel php answer more. Thank you.
We can use package Guzzle in Laravel, it is a PHP HTTP client to send HTTP requests.
You can install Guzzle through composer
composer require guzzlehttp/guzzle:~6.0
Or you can specify Guzzle as a dependency in your project's existing composer.json
{
"require": {
"guzzlehttp/guzzle": "~6.0"
}
}
Example code of POST Request in laravel, using Guzzle is as shown below,
use GuzzleHttp\Client;
class yourController extends Controller {
public function saveApiData()
{
$client = new Client();
$res = $client->request('POST', 'https://url_to_the_api', [
'form_params' => [
'client_id' => 'test_id',
'secret' => 'test_secret',
]
]);
$result= $res->getBody();
dd($result);
}
Let me clarify some stuff and try to point you in the right direction.
First, what you're attempting to do sounds like "making an API request from your web app". The difference in that wording in how I stated it vs yours is that it's more general.
You can make an API request anywhere in your application, not necessarily in your controller (Don't be afraid to make extra classes/models for things like API calls!)
I'm curious about why it "has to be" done in your controller? What's your use case?
AJAX doesn't exist on the server-side (in PHP). That's purely a javascript-specific "technology" that describes javascript making a request to a URL on the client-side.
Lastly, what are you trying to do? Do you need a user to be redirected? Or do you need to make an API call and parse the result within your application?
The cURL request you've attempted should work for making an API request. That's one of the main ways of making an API request within PHP code. It won't, however, allow a user on the front-end to see that request being made and processed. With cURL (and any API request), the processing is all happening behind the scenes in your PHP (which your users can't see).
Either use CURL the way you've been trying, or check this thread for a brief answer on doing it with the Guzzle http client. Guzzle seems to be the preferred client for use with Laravel...
Call external API function from controller, LARAVEL 4

Need assistance with cURL. Need to replace ajax call

My client wants me to implement a page. On this page I made an API call using AJAX (as shown in code).
jQuery.ajax({
url: endpoint,
type: "POST",
cache:false,
data: {
url:"link-rest/sweepstakes/claim",
userId:193298,
prizeRank:2,
sweepStakeId:186
},
dataType: "json",
headers: {
Authorization:token
},
success: function(json){
callback(json);
},
error: function(xhr, status, error){
callback(errorHandle(2));
}
});
But now he wants to use this page for SEO aswell. For that I have to make an API call in php. I have never worked with cURL before. And the examples on stackoverflow does not seem to work for me. I have Wamp Server installed and the php_curl extension has been activated. All services for wamp have also been restarted. This is what I tried to implement.
$json_url = 'link-rest/sweepstakes/claim&userId=193298&prizeRank=2&sweepStakeId=186&Authorization=ams0TGpFek5EazBNekExTmprd01EYz1NVGt6TQ';
$ch = curl_init($json_url);
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array('Content-type: application/json'),
);
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
var_dump(json_decode($result));
But all that is printed on my screen is "null". Can anyone please tell me what I am doing wrong here?
The basic problem with the code is that you are using a relative URI and not an absolute one.
You also seem to be trying to provide a request encoded in JSON, but the Ajax appears to use standard form encoding and only expects JSON in the response
A more fundamental problem is that you are using cURL in the first place. link-rest/sweepstakes/claim is presumably handled via PHP, so you should refactor out the bits you want to call into a library and then call that library from the function you are writing. (While turning the page that handles the Ajax request into a simple View around it).

Sending raw multipart data through jquery $.post() and php

i need to send raw multipart data with a php POST but without an html form... im starting the process with jquery $.post() instead (the objective is to change a twitter account's background).
How can i achieve that? This is my current (and still incomplete) code:
1) Image filename is inserted in this hidden input field:
<input type="hidden" id="profile_background_image_url" value="oats.jpg" />
2) when clicking on the submit button, a javascript function is triggered... and it calls:
$.post('helper.php',{
profile_background_image_url:$('#profile_background_image_url').val()
});
3) helper.php has
$param = array();
$param['image'] = '/www/uploads/'.$_POST['profile_use_background_image'];
$status = $connection->post('account/update_profile_background_image',$param);
Notes:
all the background files are inside the /www/uploads local directory.
im using Abraham Williams' twitteroauth library 0.2
Bottom line, in step three i need to send $param['image'] in raw multipart data to the $connection object (twitter library).
Any ideas?
Some references: http://dev.twitter.com/doc/post/account/update_profile_background_image
Yeah i see now that hes building the post fields array into a query string which means you have to manually set the content type and that the # key in the image fields wont do its magic since that only works with an array argument. More importantly i dont see a way to modify the headers without hacking the library or extending it and replacing certain functions.
I would try would be prepending # to the file path of the image param like:
$param['image'] = '#/www/uploads/'.$_POST['profile_use_background_image'];
That is the convenient way to do it with cURL, and it looks like the libray basically uses cURL to make the request, so that should work.
solved!
curl_setopt($ci, CURLOPT_POST, TRUE);
if(is_array($files)){
$post_file_array = array();
foreach($files as $key=>$value){
$post_file_array[$key] = "#{$value}";
}
curl_setopt($ci, CURLOPT_POSTFIELDS, $post_file_array);
if (!empty($postfields)) {
$url = "{$url}?{$postfields}";
}
}
else if (!empty($postfields)) {
curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
}

Categories