So I've to integrate with an API that accepts files and a field called "fileMetadata" which is a json. The curl looks like this
curl --location 'HIDDEN-URL' \
--header 'X-upload-Type: batch' \
--header 'X-AUTH-TOKEN: HIDDEN-TOKEN' \
--form 'fileMetadata="[{\"fileName\":\"G1-Entry-L2-Back+2023-03-28_01_00_00.175.jpg\",\"deviceId\":\"D-TR-0010\",\"date\":\"20230328\",\"time\":\"120000\"}]";type=application/json' \
--form 'file=@"/PATH-TO-IMG/G1-Entry-L2-Back+2023-03-28_01_00_00.175.jpg"' \
--form 'file=@"/PATH-TO-IMG/G1-Entry-L2-Back+2023-03-28_01_00_00.175.jpg"'
I can set the fileMetadata content type to json in postman like this:
And the API won't accept the request unless its like that.
In my code, I did this:
$headers = array(
'X-AUTH-TOKEN: ' . config('services.camera.X-AUTH-TOKEN'),
'X-upload-Type: batch'
);
$body = [];
$local = Storage::disk('public');
foreach($images as $key => $img){
/* try and catch file download */
//Downloading the file from a remote FTP and putting it in a temp file (So I can use it in curl)
$local->put(".temp/" . $img['fileName'], Storage::disk("ftp")->get("new/" . $img['fileName']));
$path = $local->path('.temp/' . $img['fileName']);
//creating curl file
$body['file'][$key] = curl_file_create($path, mime_content_type($path), basename($path));
}
// json encoding the file array details
$body["fileMetadata"] = json_encode($images);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, config('services.camera.url') . $batchId);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->build_post_fields($body));
$result = curl_exec($ch);
curl_close($ch);
$local->deleteDirectory('.temp');
dd($result);
I used this solution for building the post field https://stackoverflow.com/a/41144063/10321719 (because it kept giving me "Array to string conversion" error)
But it still isn't working and the API is returning bad request, I'm pretty sure because its not seeing the json from fileMetadata field as I tried it in postman without specifying "fileMetadata" content type and it returned the same error.
CURL info:
"url" => "HIDDEN"
"content_type" => "application/json"
"http_code" => 400
"header_size" => 296
"request_size" => 294
"filetime" => -1
"ssl_verify_result" => 0
"redirect_count" => 0
"total_time" => 0.525641
"namelookup_time" => 0.075162
"connect_time" => 0.153136
"pretransfer_time" => 0.260049
"size_upload" => 760.0
"size_download" => 151.0
"speed_download" => 287.0
"speed_upload" => 1445.0
"download_content_length" => -1.0
"upload_content_length" => 760.0
"starttransfer_time" => 0.260055
"redirect_time" => 0.0
"redirect_url" => ""
"primary_ip" => "HIDDEN"
"certinfo" => []
"primary_port" => 443
"local_ip" => "HIDDEN"
"local_port" => 56168
"http_version" => 3
"protocol" => 2
"ssl_verifyresult" => 0
"scheme" => "HTTPS"
"appconnect_time_us" => 259936
"connect_time_us" => 153136
"namelookup_time_us" => 75162
"pretransfer_time_us" => 260049
"redirect_time_us" => 0
"starttransfer_time_us" => 260055
"total_time_us" => 525641
The part of code that calls upload function
try {
$files = Storage::disk('ftp')->files("/new");
$unique_devices = [];
foreach($files as $file){
//breaking down the file name because it contains the API information we need
$break = explode("+", $file);
$device_id = str_replace("new/", "", $break[0]); // device id
if(!isset($break[1])){
continue;
}
if(!in_array($device_id, $unique_devices)){
// The api integration wants the user to generate a batch for each unique camera so this is basically getting unique device ids in an array
array_push($unique_devices, $device_id);
$this->info[$device_id]["fileMetadata"] = [];
}
// breaking down other important information
$file_name = str_replace("new/", "", $file);
$dateBreakDown = explode(".", $break[1]);
$date = explode("_", $dateBreakDown[0]);
$time = $date[1] . $date[2] . $date[3];
$date = str_replace("-", "", $date[0]);
//pushing it into the array, basically this contains "images" variable from the upload funciton
array_push($this->info[$device_id]["fileMetadata"], ["fileName" => $file_name, "deviceId" => "D-TR-0010"/*$device_id*/, "date" => $date, "time" => $time]);
}
$batches = $this->genBatchId($unique_devices);
foreach($this->info as $dId => $upload){
$this->uploadFiles($upload['fileMetadata'], $batches[$dId]);
}
} catch (Exception $e){
Log::debug($e->getMessage());
}