Related
The following script works:
move_uploaded_file($_FILES['file']['tmp_name'], $filename);
echo exec('curl -X POST --data-binary #' . $filename . ' http://remote.api:8888/index/add');
Following doesn't:-
We will be disabling exec() soon and will be doing plenty of hardening so the above solution will not work.
I tried the following:
move_uploaded_file($_FILES['file']['tmp_name'], $filename);
$filetype = $_FILES['file']['type'];
$ch = curl_init('http://remote.api/index/add');
curl_setopt($ch, CURLOPT_PORT, 8888);
curl_setopt($ch, CURLOPT_POST, TRUE);
$cFile = curl_file_create($filename, $filetype, $_FILES['file']['name']); // php5.5+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $cFile]);
$x = curl_exec($ch);
curl_close($ch);
The server does not respond to this workaround.
What am I missing? Please note I am using php 5.5 thus curl_create_file
Thank you for all the help :)
I'm developing a web portal which is consuming the REST API from java. By using curl I'm able to send post request and receive response easily but I'm not able to send file using CURL, it shows the error "HTTP Status 500 - Could find no Content-Disposition header within part":
Here is my code:
$filename = $_FILES['uploadedfile']['tmp_name'];
$handle = fopen($filename, "r");
$data = '#'.fread($handle, filesize($filename));
$dat = base64_encode($data);
$POST_DATA = array(
'imageName' => $dat,
"Id" => "690",
);
$boundary = '--myboundary-xxx';
var_dump($POST_DATA);
$params = json_encode($POST_DATA);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://localhost.com/Project/REST/webservice/saveImage');
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-Type:multipart/form-data; boundary=$boundary; ',
'Content-Disposition: attachment; filename:"$filename";',
'Content-Length: ' . strlen($params)
));
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($curl);
var_dump(curl_getinfo($curl));
curl_close ($curl);
var_dump($response);
echo $response;
}
Did you try
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-Type:multipart/form-data; boundary='.$boundary.'; ',
'Content-Disposition: attachment; filename='.$filename.';',
'Content-Length: ' . strlen($params)
));
I am using Jira's API to add an attachment file to a case. My issue is after my code attaches a file, and I go to the JIRA case to confirm, I see two things. First, if it is an image, I can see a thumbnail of the image. If I click it, though, I get an error saying "The requested content cannot be loaded. Please try again." Second, under the thumbnail, instead of showing the name of the file, it has the path that the file was originally uploaded from (id: c:/wamp/www/...." Is there a reason this is happening? Here is my code:
$ch = curl_init();
$header = array(
'Content-Type: multipart/form-data',
'X-Atlassian-Token: no-check'
);
$attachmentPath = $this->get_file_uploads();
//$attachmentPath comes out to be something like:
//c:/wamp/www/mySite/web/system/files/my_folder/DSC_0344_3.JPG
$data = array('file'=>"#". $attachmentPath, 'filename'=>'DSC_0344_3.JPG');
$url= 'https://mysite.atlassian.net/rest/api/2/issue/20612/attachments/';
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS ,$data);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, "myusername:mypassword");
$result = curl_exec($ch);
$ch_error = curl_error($ch);
Once the file gets added to Jira, when I log into jira, I can see the thumbnail but the title under the file is something like: c:/wamp/www/mySite/web/system/files/my_folder/DSC_0344_3.JPG instead of the file name.
thanks
You need to use:
$data = array('file'=>"#". $attachmentPath . ';filename=DSC_0344_3.JPG');
It is an issue in PHP cURL <5.5.0 but > 5.2.10, see JIRA API attachment names contain the whole paths of the posted files
When using PHP >= 5.5.0 it is better to switch to the CURLFile approach as also documented in that link.
$cfile = new CURLFile($attachmentPath);
$cfile->setPostFilename('DSC_0344_3.JPG');
$data = array('file'=>$cfile);
For anybody in the future: here's a function i wrote that works on php 7
function attachFileToIssue($issueURL, $attachmentURL) {
// issueURL will be something like this: http://{yourdomainforjira}.com/rest/api/2/issue/{key}/attachments
// $attachmentURL will be real path to file (i.e. C:\hereswheremyfilelives\fileName.jpg) NOTE: Local paths ("./fileName.jpg") does not work!
$ch = curl_init();
$headers = array(
'X-Atlassian-Token: nocheck',
'Content-type: multipart/form-data'
);
$cfile = new CURLFile($attachmentURL);
$cfile->setPostFilename(basename($attachmentURL));
$data = array("file" => $cfile);
curl_setopt_array(
$ch,
array(
CURLOPT_URL => $issueURL,
CURLOPT_VERBOSE => 1,
CURLOPT_POSTFIELDS => $data,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_USERPWD => "{username}:{password}"
)
);
$result = curl_exec($ch);
$ch_error = curl_error($ch);
if ($ch_error)
echo "cURL Error: " . $ch_error;
curl_close($ch);
}
I'm working on an application in which I'd like to be able to upload activities (GPX files) to Strava using it's API v3.
My application successfully handles the OAuth process - I'm able to request activities, etc, successfully.
However, when I try to upload an activity - it fails.
Here's the relevant sample of my code:
// $filename is the name of the GPX file
// $actual_file contains the full path
$actual_file = realpath($filename);
$url="https://www.strava.com/api/v3/uploads";
$postdata = "activity_type=ride&file=". "#" . $actual_file . ";filename=" . $filename . "&data_type=gpx";
$headers = array('Authorization: Bearer ' . $strava_access_token);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($ch, CURLOPT_POST, 3);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec ($ch);
Here's what I get in response:
{"message":"Bad Request", "errors":[{"resource":"Upload", "field":"file","code":"not a file"}]}
I then tried this:
// $filename is the name of the GPX file
// $actual_file contains the full path
$actual_file = realpath($filename);
$url="https://www.strava.com/api/v3/uploads";
$postfields = array(
"activity_type" => "ride",
"data_type" => "gpx",
"file" => "#" . $filename
);
$postdata = http_build_query($postfields);
$headers = array('Authorization: Bearer ' . $strava_access_token, "Content-Type: application/octet-stream");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($ch, CURLOPT_POST, count($postfields));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$fp = fopen($filename, 'r');
curl_setopt($ch, CURLOPT_INFILE, $fp);
$json = curl_exec ($ch);
$error = curl_error ($ch);
Here's what I get in response:
{"message":"Bad Request", "errors":[{"resource":"Upload", "field":"data","code":"empty"}]}
Clearly, I'm doing something wrong when trying to pass the GPX file.
Is it possible to provide a bit of sample PHP code to show how this should work?
For what it's worth - I'm fairly certain the GPX file is valid (it's actually a file I downloaded using Strava's export feature).
I hope that answering my own question less than one day after posting it isn't bad form. But I've got it working, so I may as well, just in case anyone else finds it useful...
// $filename is the name of the file
// $actual_file includes the filename and the full path to the file
// $strava_access_token contains the access token
$actual_file = realpath($filename);
$url="https://www.strava.com/api/v3/uploads";
$postfields = array(
"activity_type" => "ride",
"data_type" => "gpx",
"file" => '#' . $actual_file . ";type=application/xml"
);
$headers = array('Authorization: Bearer ' . $strava_access_token);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec ($ch);
Apparently, it's important not to include the CURLOPT_POST option.
Here is also a working Python example
import os
import requests
headers = {
'accept': 'application/json',
'authorization': 'Bearer <Token>',
}
dir = os.getcwd() + '/files/'
for filename in os.listdir(dir):
file = open(dir + filename, 'rb')
files = {
"file": (filename, file, 'application/gpx+xml'),
"data_type": (None, 'gpx'),
}
try:
response = requests.post('http://www.strava.com/api/v3/uploads',files=files, headers=headers)
print(filename)
print(response.text)
print(response.headers)
except requests.exceptions.RequestException as e: # This is the correct syntax
print(e)
sys.exit(1)
I'm writing an API and I'm wanting to handle file uploads from a form POST. The markup for the form is nothing too complex:
<form action="" method="post" enctype="multipart/form-data">
<fieldset>
<input type="file" name="image" id="image" />
<input type="submit" name="upload" value="Upload" />
</fieldset>
</form>
However, I'm having difficulties understanding how to handle this server-side and send along with a cURL request.
I'm familiar with sending POST requests with cURL with a data array, and resources I've read on uploading files tell me to prefix the filename with an # symbol. But these same resources have a hard-coded file name, e.g.
$post = array(
'image' => '#/path/to/myfile.jpg',
...
);
Well which file path is this? Where would I find it? Would it be something like $_FILES['image']['tmp_name'], in which case my $post array should look like this:
$post = array(
'image' => '#' . $_FILES['image']['tmp_name'],
...
);
Or am I going about this the wrong way? Any advice would be most appreciated.
EDIT: If someone could give me a code snippet of where I would go with the following code snippets then I'd be most grateful. I'm mainly after what I would send as cURL parameters, and a sample of how to use those parameters with the receiving script (let's call it curl_receiver.php for argument's sake).
I have this web form:
<form action="script.php" method="post" enctype="multipart/form-data">
<fieldset>
<input type="file" name="image />
<input type="submit" name="upload" value="Upload" />
</fieldset>
</form>
And this would be script.php:
if (isset($_POST['upload'])) {
// cURL call would go here
// my tmp. file would be $_FILES['image']['tmp_name'], and
// the filename would be $_FILES['image']['name']
}
Here is some production code that sends the file to an ftp (may be a good solution for you):
// This is the entire file that was uploaded to a temp location.
$localFile = $_FILES[$fileKey]['tmp_name'];
$fp = fopen($localFile, 'r');
// Connecting to website.
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERPWD, "email#email.org:password");
curl_setopt($ch, CURLOPT_URL, 'ftp://#ftp.website.net/audio/' . $strFileName);
curl_setopt($ch, CURLOPT_UPLOAD, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 86400); // 1 Day Timeout
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'CURL_callback');
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localFile));
curl_exec ($ch);
if (curl_errno($ch)) {
$msg = curl_error($ch);
}
else {
$msg = 'File uploaded successfully.';
}
curl_close ($ch);
$return = array('msg' => $msg);
echo json_encode($return);
For people finding this post and using PHP5.5+, this might help.
I was finding the approach suggested by netcoder wasn't working. i.e. this didn't work:
$tmpfile = $_FILES['image']['tmp_name'];
$filename = basename($_FILES['image']['name']);
$data = array(
'uploaded_file' => '#'.$tmpfile.';filename='.$filename,
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
I would receive in the $_POST var the 'uploaded_file' field - and nothing in the $_FILES var.
It turns out that for php5.5+ there is a new curl_file_create() function you need to use. So the above would become:
$data = array(
'uploaded_file' => curl_file_create($tmpfile, $_FILES['image']['type'], $filename)
);
As the # format is now deprecated.
This should work:
$tmpfile = $_FILES['image']['tmp_name'];
$filename = basename($_FILES['image']['name']);
$data = array(
'uploaded_file' => '#'.$tmpfile.';filename='.$filename,
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
// set your other cURL options here (url, etc.)
curl_exec($ch);
In the receiving script, you would have:
print_r($_FILES);
/* which would output something like
Array (
[uploaded_file] => Array (
[tmp_name] => /tmp/f87453hf
[name] => myimage.jpg
[error] => 0
[size] => 12345
[type] => image/jpeg
)
)
*/
Then, if you want to properly handle the file upload, you would do something like this:
if (move_uploaded_file($_FILES['uploaded_file'], '/path/to/destination/file.zip')) {
// do stuff
}
For my the # symbol did not work, so I do some research and found this way and it work for me, I hope this help you.
$target_url = "http://server:port/xxxxx.php";
$fname = 'file.txt';
$cfile = new CURLFile(realpath($fname));
$post = array (
'file' => $cfile
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");
curl_setopt($ch, CURLOPT_HTTPHEADER,array('Content-Type: multipart/form-data'));
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$result = curl_exec ($ch);
if ($result === FALSE) {
echo "Error sending" . $fname . " " . curl_error($ch);
curl_close ($ch);
}else{
curl_close ($ch);
echo "Result: " . $result;
}
It works for me when sending an attachment to Mercadolibre, through its messaging system.
The anwswer https://stackoverflow.com/a/35227055/7656744
$target_url = "http://server:port/xxxxx.php";
$fname = 'file.txt';
$cfile = new CURLFile(realpath($fname));
$post = array (
'file' => $cfile
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");
curl_setopt($ch, CURLOPT_HTTPHEADER,array('Content-Type: multipart/form-data'));
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$result = curl_exec ($ch);
if ($result === FALSE) {
echo "Error sending" . $fname . " " . curl_error($ch);
curl_close ($ch);
}else{
curl_close ($ch);
echo "Result: " . $result;
}
cURL file object in procedural method:
$file = curl_file_create('full path/filename','extension','filename');
cURL file object in Oop method:
$file = new CURLFile('full path/filename','extension','filename');
$post= array('file' => $file);
$curl = curl_init();
//curl_setopt ...
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($curl);
curl_close($curl);
we can upload image file by curl request by converting it base64 string.So in post we will send file string and then covert this in an image.
function covertImageInBase64()
{
var imageFile = document.getElementById("imageFile").files;
if (imageFile.length > 0)
{
var imageFileUpload = imageFile[0];
var readFile = new FileReader();
readFile.onload = function(fileLoadedEvent)
{
var base64image = document.getElementById("image");
base64image.value = fileLoadedEvent.target.result;
};
readFile.readAsDataURL(imageFileUpload);
}
}
then send it in curl request
if(isset($_POST['image'])){
$curlUrl='localhost/curlfile.php';
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $curlUrl);
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS, 'image='.$_POST['image']);
$result = curl_exec($ch);
curl_close($ch);
}
see here http://technoblogs.co.in/blog/How-to-upload-an-image-by-using-php-curl-request/118
Here is my solution, i have been reading a lot of post and they was really helpfull, finaly i build a code for small files, with cUrl and Php, that i think its really usefull.
public function postFile()
{
$file_url = "test.txt"; //here is the file route, in this case is on same directory but you can set URL too like "http://examplewebsite.com/test.txt"
$eol = "\r\n"; //default line-break for mime type
$BOUNDARY = md5(time()); //random boundaryid, is a separator for each param on my post curl function
$BODY=""; //init my curl body
$BODY.= '--'.$BOUNDARY. $eol; //start param header
$BODY .= 'Content-Disposition: form-data; name="sometext"' . $eol . $eol; // last Content with 2 $eol, in this case is only 1 content.
$BODY .= "Some Data" . $eol;//param data in this case is a simple post data and 1 $eol for the end of the data
$BODY.= '--'.$BOUNDARY. $eol; // start 2nd param,
$BODY.= 'Content-Disposition: form-data; name="somefile"; filename="test.txt"'. $eol ; //first Content data for post file, remember you only put 1 when you are going to add more Contents, and 2 on the last, to close the Content Instance
$BODY.= 'Content-Type: application/octet-stream' . $eol; //Same before row
$BODY.= 'Content-Transfer-Encoding: base64' . $eol . $eol; // we put the last Content and 2 $eol,
$BODY.= chunk_split(base64_encode(file_get_contents($file_url))) . $eol; // we write the Base64 File Content and the $eol to finish the data,
$BODY.= '--'.$BOUNDARY .'--' . $eol. $eol; // we close the param and the post width "--" and 2 $eol at the end of our boundary header.
$ch = curl_init(); //init curl
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'X_PARAM_TOKEN : 71e2cb8b-42b7-4bf0-b2e8-53fbd2f578f9' //custom header for my api validation you can get it from $_SERVER["HTTP_X_PARAM_TOKEN"] variable
,"Content-Type: multipart/form-data; boundary=".$BOUNDARY) //setting our mime type for make it work on $_FILE variable
);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/1.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0'); //setting our user agent
curl_setopt($ch, CURLOPT_URL, "api.endpoint.post"); //setting our api post url
curl_setopt($ch, CURLOPT_COOKIEJAR, $BOUNDARY.'.txt'); //saving cookies just in case we want
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); // call return content
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1); navigate the endpoint
curl_setopt($ch, CURLOPT_POST, true); //set as post
curl_setopt($ch, CURLOPT_POSTFIELDS, $BODY); // set our $BODY
$response = curl_exec($ch); // start curl navigation
print_r($response); //print response
}
With this we shoud be get on the "api.endpoint.post" the following vars posted
You can easly test with this script, and you should be recive this debugs on the function postFile() at the last row
print_r($response); //print response
public function getPostFile()
{
echo "\n\n_SERVER\n";
echo "<pre>";
print_r($_SERVER['HTTP_X_PARAM_TOKEN']);
echo "/<pre>";
echo "_POST\n";
echo "<pre>";
print_r($_POST['sometext']);
echo "/<pre>";
echo "_FILES\n";
echo "<pre>";
print_r($_FILEST['somefile']);
echo "/<pre>";
}
Here you are it should be work good, could be better solutions but this works and is really helpfull to understand how the Boundary and multipart/from-data mime works on php and curl library,
My Best Reggards,
my apologies about my english but isnt my native language.