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

如何通过Guzzle将Symfony Request传递至另一个控制器?

解决Symfony网关转发文件上传请求的问题

核心原因

文件上传请求采用multipart/form-data格式,Symfony解析该请求时会一次性读取php://input流,导致后续调用$request->getContent()无法获取到原始请求体;直接转发字符串格式的请求体也无法正确还原multipart结构,最终导致文档微服务接收不到文件。

正确解决方案:重新构建Guzzle Multipart请求

网关需要基于Symfony解析后的参数和文件,重新构建符合Guzzle要求的multipart请求体,而不是直接转发原始请求内容。

步骤与代码示例

  1. 收集POST参数和上传文件
  2. 构建Guzzle的multipart数组
  3. 发送请求时使用multipart选项而非body
use GuzzleHttp\Client;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Response;

// 1. 从当前请求中获取解析后的参数和文件
$formParams = $request->request->all();
$uploadedFiles = $request->files->all();

// 2. 构建multipart请求数据
$multipartData = [];

// 添加普通POST参数,处理数组类型参数
foreach ($formParams as $key => $value) {
    if (is_array($value)) {
        foreach ($value as $item) {
            $multipartData[] = [
                'name' => "{$key}[]",
                'contents' => (string)$item
            ];
        }
    } else {
        $multipartData[] = [
            'name' => $key,
            'contents' => (string)$value
        ];
    }
}

// 添加上传的文件
foreach ($uploadedFiles as $key => $file) {
    if ($file instanceof UploadedFile && $file->isValid()) {
        $multipartData[] = [
            'name' => $key,
            'contents' => fopen($file->getRealPath(), 'r'),
            'filename' => $file->getClientOriginalName()
        ];
    }
}

// 3. 用Guzzle发送请求到文档微服务
$client = new Client();
$response = $client->post('http://your-document-service/upload-endpoint', [
    'multipart' => $multipartData,
    // 传递必要的请求头(如认证Token)
    'headers' => [
        'Authorization' => $request->headers->get('Authorization'),
        // 无需手动设置Content-Type,Guzzle会自动生成带boundary的正确头
    ]
]);

// 返回微服务的响应给前端
return new Response(
    $response->getBody()->getContents(),
    $response->getStatusCode(),
    $response->getHeaders()
);

关键注意事项

  • 不要手动设置Content-Type: multipart/form-data,Guzzle会根据multipart数组自动生成包含正确boundary的请求头,手动设置会导致格式错误。
  • 确保文档微服务的控制器仍使用$request->files->get('file_key')获取文件,和直接Postman调用的逻辑保持一致。
  • 对于数组类型的参数(如urls),需要拆分为多个name=key[]的项,否则微服务无法正确解析数组参数。

内容的提问来源于stack exchange,提问作者Augustin D'ille

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 12:49:58