You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 12:54:27