Laravel HttpClient Guzzle同时传图片数组报contents key required错误
报错原因
调用attach()方法上传文件时,Laravel HTTP客户端会自动将请求编码格式切换为multipart/form-data,该格式下底层依赖的Guzzle HTTP库要求每个表单字段必须以['键名' => ['contents' => '字段值']]的结构传入,不支持直接识别原生PHP数组类型的参数。
你直接将branches、tags数组传入post参数时,客户端无法自动将数组解析为符合要求的multipart字段结构,就会抛出A 'contents' key is required错误。
这也能对应你测试时的互斥现象:
- 去掉attach逻辑后,请求默认使用
application/x-www-form-urlencoded编码,该编码下客户端会自动处理数组参数,所以普通字段、数组字段都能正常提交,但无法传输文件 - 去掉数组参数后,所有传入的字段都是单值类型,客户端可以自动转换为符合multipart要求的结构,所以文件能正常上传,但数组参数无法传递
解决方案
手动将所有数组类型的表单字段扁平化,按照PHP数组的表单命名规则(即数组名[索引]的键名格式)拆分为单值字段,和普通字段一起传入post参数即可,不需要额外修改文件上传的逻辑。
修正后的代码如下:
// 初始化请求并处理多图上传 $response = Http::(); for($i = 0 ; $i < count($request['images']); $i++) { $response = $response->attach( 'images['.$i.']', file_get_contents($request['images'][$i]), 'image.png' ); } // 组装基础单值表单参数 $formData = [ 'name' => 'name', 'discount' => $request->discount, 'type' => $request->type, 'category' => $request->category, 'actual_price' => $request->actual_price, 'price' => $request->price, 'after_discount' => $request->after_discount, 'expiry' => $request->expiry, 'description' => $request->description, ]; // 扁平化branches数组为单值字段 foreach ($request['branches'] as $idx => $branch) { $formData["branches[{$idx}]"] = $branch; } // 扁平化tags数组为单值字段 foreach ($request['tags'] as $idx => $tag) { $formData["tags[{$idx}]"] = $tag; } // 发起请求 $response = $response->post('...WEB_URL_HIDDEN.../api/merchant/createDeal', $formData); dd($response->json());
如果你的branches或tags是多维嵌套数组,只需要递归遍历数组,将所有层级的键拼接为a[b][c][d]格式的字符串键,保证传入的$formData里不存在数组类型的值,就可以正常提交。
内容的提问来源于stack exchange,提问作者AbdurRehman
相关产品推荐
相关产品推荐

