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

Laravel8使用Guzzle调用Mirakl API上传form-param文件报400错误

现有代码核心错误
  • 文件上传字段传值错误:Guzzle multipart 格式上传文件时,contents 参数需要传入文件流资源,当前代码传入本地磁盘路径字符串,相当于仅上传了路径文本,服务端无法接收到真实文件内容。
  • order_documents 参数格式错误:Mirakl 接口接收 multipart/form-data 格式的表单数组参数,不需要手动将参数序列化为JSON字符串,当前写法会导致服务端无法解析结构化的文档元数据。
  • 请求头冲突风险:如果配置的请求头中手动指定了 Content-Type(尤其是固定值的 multipart/form-data 或 application/json),会覆盖Guzzle自动生成的带正确boundary标识的Content-Type头,导致服务端无法解析表单内容。
  • 无错误捕获逻辑:接口返回400时无法直接拿到服务端返回的具体错误提示,排查效率低。
修正后可运行代码

调整逻辑:直接按表单数组规则构造order_documents参数,上传时传入真实文件流,移除手动配置的冲突请求头,增加异常捕获方便定位问题。

public function upload_order(Request $request)
{
    $order_id = $request->order_id;
    $filePath = '';
    $fileName = '';
    if ($uploadedFile = $request->file('files')) {
         $fileName = $uploadedFile->getClientOriginalName();
         Storage::disk('invoice')->put($fileName, file_get_contents($uploadedFile->getRealPath()));
         $filePath = Storage::disk('invoice')->path($fileName);
    }

    $multipartData = [];
    // 按表单数组格式构造文档元数据,不做JSON序列化
    $multipartData[] = [
        'name' => 'order_documents[0][file_name]',
        'contents' => $fileName
    ];
    $multipartData[] = [
        'name' => 'order_documents[0][type_code]',
        'contents' => $request->type_code
    ];
    // 传入打开的文件流资源,而非路径字符串
    $multipartData[] = [
        'name' => 'files',
        'contents' => fopen($filePath, 'r'),
        'filename' => $fileName
    ];

    $configApi = $this->configApi($this->getMarketplaceID($request->marketplace), auth()->user()->id);
    $url = $configApi['url'].'/api/orders/'.$order_id.'/documents';
    
    // 移除手动配置的Content-Type头,交由Guzzle自动生成带合法boundary的头
    $headers = $configApi['headers'];
    unset($headers['Content-Type'], $headers['content-type']);

    $client = new Client(['verify' => false]);
    try {
        $response = $client->request(
            'POST',
            $url,
            [
                'multipart' => $multipartData,
                'headers' => $headers
            ]
        );
        return json_decode($response->getBody(), true);
    } catch (\GuzzleHttp\Exception\ClientException $e) {
        // 触发4xx错误时直接输出接口返回的具体错误信息,快速定位问题
        dd($e->getResponse()->getBody()->getContents());
    }
}
  • 多文件上传场景只需按索引对齐参数即可,第二个文件对应order_documents[1][file_name]、order_documents[1][type_code],文件字段命名为files[1],依次类推。
  • 如果使用Laravel自带HTTP客户端,逻辑完全一致:文件传文件实例/流资源,元数据按数组格式传递,不手动设置Content-Type头即可。

内容的提问来源于stack exchange,提问作者Tanvir Hasan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:12:09