如何在PHP CURL的POST字段中为key指定Content-Type?
对接含JSON类型字段的文件上传API返回400 Bad Request问题
我需要对接一个支持文件上传且包含JSON类型字段fileMetadata的API。对应的CURL命令中,fileMetadata字段需指定type=application/json;在Postman中设置该字段的Content-Type为JSON后,请求才能被API接受。
我编写了PHP代码实现对接:先从FTP下载文件到本地临时目录,通过curl_file_create创建文件对象,将fileMetadata字段JSON编码后加入POST参数,使用第三方函数处理POST字段避免“Array to string conversion”错误,但API仍返回400 Bad Request。经测试,怀疑是fileMetadata字段的Content-Type未被正确识别(Postman中不设置该类型时会返回相同错误)。
相关代码及CURL请求信息如下:
上传逻辑代码
$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){ //从远程FTP下载文件并存入临时文件(用于CURL上传) $local->put(".temp/" . $img['fileName'], Storage::disk("ftp")->get("new/" . $img['fileName'])); $path = $local->path('.temp/' . $img['fileName']); //创建CURL文件对象 $body['file'][$key] = curl_file_create($path, mime_content_type($path), basename($path)); } //对文件数组详情进行JSON编码 $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);
CURL请求信息
"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
调用上传函数的代码
try { $files = Storage::disk('ftp')->files("/new"); $unique_devices = []; foreach($files as $file){ //拆分文件名以获取所需API信息 $break = explode("+", $file); $device_id = str_replace("new/", "", $break[0]); //设备ID if(!isset($break[1])){ continue; } if(!in_array($device_id, $unique_devices)){ //API要求每个设备生成一个批次,此处收集唯一设备ID array_push($unique_devices, $device_id); $this->info[$device_id]["fileMetadata"] = []; } //拆分其他关键信息 $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]); //将信息加入数组(对应上传函数的$images变量) 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()); }
内容的提问来源于stack exchange,提问作者Tghosh
相关产品推荐
相关产品推荐

