I am having this problem from last few days to develop a CURL request in php to post file data to an API.
Here is the CURL request
$ curl --request POST \
--url 'UPLOAD_URL' \
--upload-file 'PATH_TO_FILE' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
for PATH_TO_FILE I have tried each and every method published over the web and stackoverflow too.
here is my PHP code
<?php
header('Content-Type: application/json');
$sheader = array('Authorization: Bearer '.$_SESSION['access_token']);
$filename = $_FILES['upload-file']['name'];
$filedata = $_FILES['upload-file']['tmp_name'];
$filesize = $_FILES['upload-file']['size'];
$filetype = $_FILES['upload-file']['type'];
if($filename != '')
{
$ch = curl_init();
$cFile = new CURLFile(realpath($filename), $filetype, 'harish.jpg');
//$cFile = '#'. realpath($filename);
$data = array('upload-file' => $cFile);
curl_setopt($ch, CURLOPT_POSTFIELDS, $cFile);
//curl_setopt($ch, CURLOPT_POSTFIELDS, realpath($filename));
curl_setopt($ch, CURLOPT_URL, $_POST['upload_url']);
curl_setopt($ch, CURLOPT_HTTPHEADER, $sheader);
curl_exec($ch);
echo json_encode($ch);
//echo json_encode(array('filename'=>$filename, 'temp_path'=>$filedata, 'basepath'=>realpath($filename)));
} else {
echo 'There is no file selected';
}
Mostly the solution i have found on the web are these two mentioned below
Method 1 (for php < 5.5)
'#'.$filepath
Method 2 (for php > 5.5)
CURLFile($filename, $filetype, 'somefile.jpg');
or
curl_file_create($filedata, 'image/jpeg', $filename);
None of the above worked for me. I have use realpath($filename) too inside CURLFile to fetch absolute path of the file, but sadly that also not worked.
I admit that CURLFile documentation is slightly ambiguous but the first constructor argument, $name, is in fact the physical path to the actual file you want to send, not the "friendly" name (which goes in the optional third argument, $postname). You should note there's something wrong since you never tell Curl about $_FILES['upload-file']['tmp_name']—it has no way to know what file you want to send.
So:
$filename = $_FILES['upload-file']['name'];
$filedata = $_FILES['upload-file']['tmp_name'];
$filesize = $_FILES['upload-file']['size'];
$filetype = $_FILES['upload-file']['type'];
$cFile = new CURLFile($filedata, $filetype, 'harish.jpg')
You aren't being notified about this because you're skipping error checking. You don't check the return value of any function, neither call curl_error() anywhere in your code.
One more error you have is that you pass the CURLFile instance this way:
curl_setopt($ch, CURLOPT_POSTFIELDS, $cFile);
Correct syntax should be like:
curl_setopt($ch, CURLOPT_POSTFIELDS, ['give_a_nice_post_name_here' => $cFile]);
Related
I am trying to upload a file to a Google Signed URL with cURL in PHP.
I have the file being posted from a form and can access it with the $_FILES var.
However the file that actually gets uploaded is not the right file and I think it is to do with how I am handling the tmp file.
$file_name = $_FILES['file']['name'];
$temp_name = $_FILES['file']['tmp_name'];
// $file = fopen($temp_name, 'r');
// $file = realpath($temp_name);
$request = curl_init($request_url);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_POSTFIELDS, $file);
curl_setopt($request, CURLOPT_HTTPHEADER, array('Content-Type:text/plain','Authorization:'.$token));
curl_setopt($request, CURLOPT_CUSTOMREQUEST, 'PUT');
$response = curl_exec($request);
$errors = curl_error($request);
curl_close($request);
var_dump($response);
var_dump($errors);
The following works as expected with content-type text instead of audio even though its a wav file.
curl -v -X PUT --upload-file file.wav --header "Content-Type: text/plain" request_url
Edit
I have tried this:
$file = new CurlFile($temp_name,$mime_type,$file_name);
but this just crashes my page altogether.
I think it may be to do with how I am calling the request, so I wanted to create a cURL function that I can just pass the url and data to for all my requests like so:
$file = new CurlFile($temp_name,$mime_type,$file_name);
$result = curl_request($conn,$signed_url,$file,'text/plain','PUT');
Then my function is like this:
function curl_request($conn,$request_url,$request_data,$content_type,$request_type){
$api_username = 'API username';
$stmt = $conn->prepare("SELECT * FROM config WHERE setting=:setting");
$stmt->bindParam(':setting', $api_username);
$stmt->execute();
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
foreach($stmt->fetchAll() as $key=>$row) {
$username = $row['value'];
}
$api_key = 'API key';
$stmt = $conn->prepare("SELECT * FROM config WHERE setting=:setting");
$stmt->bindParam(':setting', $api_key);
$stmt->execute();
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
foreach($stmt->fetchAll() as $key=>$row) {
$key = $row['value'];
}
$data = array(
'username' => $username,
'password' => $key
);
$payload = json_encode($data);
$initial_request = curl_init('https://example.com/auth');
curl_setopt($initial_request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($initial_request, CURLOPT_POSTFIELDS, $payload);
curl_setopt($initial_request, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
$initial_response = curl_exec($initial_request);
$initial_errors = curl_error($initial_request);
curl_close($initial_request);
$decoded_response = (array)json_decode($initial_response);
$token = $decoded_response['token'];
$request = curl_init($request_url);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_POSTFIELDS, $request_data);
curl_setopt($request, CURLOPT_HTTPHEADER, array('Content-Type:'.$content_type,'Authorization:'.$token));
curl_setopt($request, CURLOPT_CUSTOMREQUEST, $request_type);
$response = curl_exec($request);
$errors = curl_error($request);
curl_close($request);
if(empty($errors)){
return $response;
}else{
return $errors;
}
}
This works when I had $file = fopen($temp_name, 'r'); but the file uploaded was a weird file.
Edit 2
This is what the file looks like when the person at the other end of this API tries to open it.
this is what you want: remove CURLOPT_POSTFIELDS altogether, and replace CURLOPT_CUSTOMREQUEST=>'PUT' with CURLOPT_UPLOAD=>1 and replace 'r' with 'rb', and use CURLOPT_INFILE (you're supposed to use INFILE instead of POSTFIELDS),
$fp = fopen($_FILES['file']['tmp_name'], "rb");
curl_setopt_array($ch,array(
CURLOPT_UPLOAD=>1,
CURLOPT_INFILE=>$fp,
CURLOPT_INFILESIZE=>$_FILES['file']['size']
));
This works when I had $file = fopen($temp_name, 'r');
never use the r mode, always use the rb mode (short for "binary mode"), weird things happen if you ever use the r mode on Windows, r is short for "text mode" - if you actually want text mode, use rt (and unless you really know what you're doing, you don't want the text mode, ever, unfortunate that it's the default mode),
but the file uploaded was a weird file. (...) This is what the file looks like when the person at the other end of this API tries to open it.
well you gave CURLOPT_POSTFIELDS a resource. CURLOPT_POSTFIELDS accepts 2 kinds of arguments, #1: an array (for multipart/form-data requests), #2: a string (for when you want to specify the raw post body data), it does not accept resources.
if the php curl api was well designed, you would get an InvalidArgumentException, or a TypeError, when giving CURLOPT_POSTFIELDS a resource. but it's not well designed. instead, what happened is that curl_setopt implicitly casted your resource to a string, hence resource id #X , it's the same as doing
curl_setopt($request, CURLOPT_POSTFIELDS, (string) fopen(...));
I am trying to convert this curl request to php.
curl -X POST -F "file=#test_img.jpg" "http://127.0.0.1:5000/FileUploading/UploadImage/"test_img.jpg"
This request is working correctly with the following flask-RESTful code
class UploadImage(Resource):
def post(self, fname):
file = request.files['file']
if file:
# From flask uploading tutorial
filename = secure_filename(file.filename)
file.save(os.path.join("Images/", filename))
return jsonify({"Path": "Images/" + filename})
else:
# return error
return {'False'}
However, the following php curl request returns error 400 as it seems the request.files parameter is empty.
$file_name = "test_img.jpg";
$post_data = array(
"file" => "#" . $file_name,
"type" => 'image/jpg'
);
$ch = curl_init();
debug_to_console(http_build_query($post_data));
$host = "http://127.0.0.1:5000";
$url = $host . "/FileUploading/UploadImage/" . $file_name;
debug_to_console($url);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
$file_param = 'file=' . $file_name;
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
$headers = array();
$headers[] = "Content-Type: multipart/form-data";
debug_to_console($headers);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
debug_to_console('Error:' . curl_error($ch));
}
curl_close($ch);
I don't know what i am doing wrong in this php request
first off, don't try to upload files using the # method, it was deprecated in PHP 5.5, disabled-by-default in PHP 5.6, and completely removed in PHP 7.0.0, in modern PHP, use CURLFile to upload files. also in line 10 you don't urlencode $file_name, that's a bug. and in line 17 you're trying to encode it to application/x-www-form-urlencoded-format (via http_build_query), but the command you're trying to convert is using multipart/form-data-format, when you give CURLOPT_POSTFIELDS a string (as returned by http_build_query), curl will send it as application/x-www-form-urlencoded by default but to make curl send it in multipart/form-data-format (as you want), set CURLOPT_POSTFIELDS to an array, not a string, and curl will send it in multipart/form-data.
I have an existing PHP script, which essentially connects to 2 databases each on a different server and performs a few MySQL queries on each. The ultimate results are stored in a data array which is used to write said results into a JSON file.
All of this works perfectly. The data is inserted into the mysql table correctly and the JSON file is exactly the way it should be.
However, I need to add a block to the end of my script that makes a POST request to one of our affiliate's API and upload the info there. We're currently manually uploading this JSON file to the api instance but we have the configuration data for their server to use in a POST request now so that when this script is run it automatically sends the data rather than us having to manually update it.
The main thing is I'm not exactly sure how to go about that. I've started with code for doing this but I'm not familiar with cURL so I don't know the best way to structure this in php.
Here is an example the affiliate gave me in cURL command line syntax:
curl \
-H "Authorization: Token AUTH_TOKEN" \
-H "Content-Type: CONTENT_TYPE" \
-X POST \
-d '[{"email": "jason#yourcompany.com", "date": "8/16/2016", "calls": "3"}]'
\
https://endpoint/api/v1/data/DATA_TYPE/
I have my auth token, my endpoint URL and my content type is JSON, which can be seen in my code below. Also, I have an array instead of the example for the body above.
and here's the affected part of my code:
//new array specifically for the final JSON file
$content2 = [];
//creating array for new fetch since it now has the updated extension IDs
while ($d2 = mysqli_fetch_array($data2, MYSQLI_ASSOC)) {
// Store the current row
$content2[] = $d2;
}
// Store it all into our final JSON file
file_put_contents('ambitionLog.json', json_encode($content2, JSON_PRETTY_PRINT ));
//Beginning code to upload to Ambition API via POST
$url = 'endpoint here';
//Initiate CURL
$ch = curl_init($url);
//JSON data
$jsonDataEncodeUpload = json_encode($content2, JSON_PRETTY_PRINT);
//POST via CURL
curl_setopt($ch, CURLOPT_POST, 1);
//attach JSON to post fields
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncodeUpload);
//set content type
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
//execuate request
$postResult = curl_exec($ch);
So, like I said, nothing about the file or the data needs to be changed, I just need to have this cURL section take the existing array that's being written to a JSON file and upload it to the API via post. I just need help making my php syntax for curl match the command line example.
Thanks for any possible help.
Have you tried with file_get_contents ( http://en.php.net/file_get_contents ).
$postdata = http_build_query(
array(
'var1' => 'some content',
'var2' => 'doh'
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($opts);
$result = file_get_contents('http://example.com/submit.php', false, $context);
I have found the answer on stackoverflow How to post data in PHP using file_get_contents?
Here is worked example of code. Check $err may be it will be helpful.
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST('data'));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type:application/json']);
$result = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$err = curl_error($ch);
curl_close($ch);
I am using cURL for the first time. I have to send one image file and one audio file posted by the user.
My cURL code is working, but instead of an image file and an audio file my code is sending a .tmp file.
I googled it, but in every example I found they have used realpath of file directly.
I tried to find real path of the file, but I didn't find any solution.
Here is my code block in which I am collecting all data in an array to pass it to cURL:
$name = $_POST['name'];
$image = $_POST['image']['name'];
$imagetmp = $_POST['image']['tmp_name'];
$imagesize = $_POST['image']['size'];
$imagepath = '#'.$imagetmp;
$audio = $_POST['audio']['name'];
$audiotmp = $_POST['audio']['tmp_name'];
$audiosize = $_POST['audio']['size'];
$audiopath = '#'.$audiotmp;
$data = array("name" => $name, "image"=> $imagepath, "audio" => $audiopath); //array to sned data using cURL
//my cURL code to post data
Where am I doing wrong? How to send files using cURL?
This is what I used to post file data:
$filedata = file_get_contents('file_location/filename.jpg');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $filedata);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/octet-stream'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$return = curl_exec($ch);
curl_close($ch);
You can use file=#path with curl
curl -kiSs -X POST https://<domain>/path/to/api/files/ \
-F "param1=param2" \
-F "file=#/path/to/test.xlsx" \
-H "Authorization":"bearer eyJhbGciOiJIUzI1NiIsIn"
File successfully uploaded (test.xlsx!)
I'm trying to upload a file to google drive using http header and CURL post, and I get a "not found" returned from google error.
I think it's because of the way Im uploading the file via CURL, Because I never Did it.
Here's My Code :
$file = file_get_contents("./ima.jpg");
$length = strlen($file);
test($file,$length);
function test($file,$length){
$url2="https://www.googleapis.com/upload/drive/v2/filesuploadType=media";
$header = array(
"Content-Type: image/jpeg",
"Content-Length:$length ",
"Authorization: Bearer $token",
);
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url2);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,false);
curl_setopt ($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch,CURLOPT_POST,true);
curl_setopt($ch,CURLOPT_POSTFIELDS,$file);
$data2 = curl_exec($ch);
echo $data2;
curl_close($ch);
}
The Token is set in a variable token, and it is a valid token because it works with listing files from google drive, Thank you !
uploadType is a parameter to the URL and needs to be separated using ?, which means that in your case the URL should most likely be;
$url2="https://www.googleapis.com/upload/drive/v2/files?uploadType=media";
See here for more detailed documentation.