Reputation: 6126
Maybe someone can help me? I do not get on with this problem
I have a POST array from a formualar and a file already existing on the server. The task is to send the POST data and the file via CURL PUT to a URL.
I've been trying to solve the problem for hours/days now
I have set the header Content-type: application/octet-stream
and the fields with $ch->setOption(CURLOPT_POSTFIELDS, http_build_query($data)
The POST data looks like this:
$data = array (
'field1' => 'lorem',
'field2' => 'ipsum',
'field3' => 'dolor'
);
Using instructions (php.net, stackoverflow etc.)
https://kb.detlus.com/articles/php/upload-files-using-curl/
https://www.php.net/manual/de/curlfile.construct.php
Is it possible to use cURL to stream upload a file using POST?
I try to send the file
Does not work
$data = array (
'field1' => 'lorem',
'field2' => 'ipsum',
'field3' => 'dolor'
'file' => '@'.realpath('/abs/path/file.xlsx');
);
neither
$data = array (
'field1' => 'lorem',
'field2' => 'ipsum',
'field3' => 'dolor'
);
$data['file'] = curl_file_create('/abs/path/file.xlsx'], mime_content_type('/abs/path/file.xlsx'), 'file.xlsx');
this leads to the following array
$data = array (
'field1' => 'lorem',
'field2' => 'ipsum',
'field3' => 'dolor',
'file' =>
array (
'file' =>
CURLFile::__set_state(array(
'name' => '/abs/path/file.xlsx',
'mime' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'postname' => '/abs/path/file.xlsx',
)),
)
);
Depending on the version I try I get a 400 or 500 error.
Does anyone have a tip that can help me? What am I doing wrong?
Upvotes: 0
Views: 1404
Reputation: 6126
Thanks for your help!!!
Solution => Content-Type: multipart/form-data
Upvotes: 0
Reputation: 204
I think the main problem here is that you're using the wrong content type.
For file uploads you should be using "Content-Type: multipart/form-data". Taken from Wikipedia (in the multipart subtypes) MIME
The MIME type multipart/form-data is used to express values submitted through a form. Originally defined as part of HTML 4.0, it is most commonly used for submitting files with HTTP. It is specified in RFC 7578, superseding RFC 2388.
I wrote this snippet, hope this can help you (sorry for the non-OOP version of the code, I don't have a PHP 8 install, I'm using PHP 7.4, but you can "translate" it easily :D):
<?php
//This is a dummy data array, will contain your form fields (Advice: never trust user input, always check the values given before submitting)
$data = [
'field1' => 'value',
'field2' => 'value2',
'field3' => 123
];
//The path to the file you want to upload
$fileName = 'somefile.xlsx';
$filePath = './../files/'.$fileName;
//Security check
if (file_exists($filePath))
{
//Adding the file to the $data array
$data['file'] = curl_file_create($filePath, mime_content_type($filePath), $fileName);
//Initialize the cURL handle
$ch = curl_init('https://some-random-site.com/api/some/random/endpoint');
//Set the request method (HTTP verb)
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
//This will make curl "return" the response as string when we call curl_exec()
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//This SHALL NOT be used in production, unless you know the implications!!! But, if you have an HTTPS endpoint with a self-signed certificate you can skip checks
//curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//======
//We set the data we want to send (curl will "transform" this for us
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
//Here the important part, setting the right content-type
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: multipart/form-data']);
//Execute the call and get the response as string
$res = curl_exec($ch);
if ($res === false)
{
//An error occurred, print out
echo 'ERROR: '.curl_error($ch);
}
else
{
//Execution succeeded, do whatever with the response
//Hint: this does not mean that the server answered with a success status but rather, it indicates that the curl execution has succeeded
//If you want to check the HTTP status of the request you can get it like this:
//$info = curl_getinfo($curl);
//echo $info['http_code'];
//Do whatever with the response (I'm just printing it).
echo $res;
}
curl_close($ch);
}
else
{
echo 'File not found.';
}
I really hope this can help, unfortunately I don't know the URL/API you're submitting the request to so I can't test it on your endpoint. I made an endpoint myself:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'PUT')
{
$c = file_get_contents('php://input');
die(var_dump($c));
}
The output I got showed me all the fields and the file upload.
--------------------------05a7619c906d94df Content-Disposition: form-data; name="field1" value
--------------------------05a7619c906d94df Content-Disposition: form-data; name="field2" value2
--------------------------05a7619c906d94df Content-Disposition: form-data; name="field3" 123
--------------------------05a7619c906d94df Content-Disposition: form-data; name="file"; filename="./../conf/test.xlsx" Content-Type:
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
........LOTS_OF_BYTES_OF_THE_XLSX_FILE_:P......
--------------------------05a7619c906d94df--
Upvotes: 1