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--