当前位置: 首页 > 知识库问答 >
问题:

Symfony无法识别通过Guzzle multipart/form-data请求上传的多个文件

益阳平
2023-03-14

环境:Guzzle 6 Symfony 2.3

通过Guzzle POST请求上传多个文件应使用多部分请求完成。因此,我将$options数组配置为:

Array
(
[multipart] => Array
    (
        [0] => Array
            (
                [name] => filename-0
                [contents] => Resource id #440
                [filename] => filename-0
            )

        [1] => Array
            (
                [name] => filename-1
                [contents] => Resource id #441
                [filename] => filename-1
            )

        [2] => Array
            (
                [name] => filename-2
                [contents] => Resource id #442
                [filename] => filename-2
            )

    )

[headers] => Array
    (
        [Accept] => application/json
        [Content-Type] => multipart/form-data
        [Accept-Language] => de
    )

[allow_redirects] =>
[http_errors] =>

)

多部分数组中的资源是fopen()的结果。

并使用

$response = $this->client->post(
    '/someUrl/someAction',
    $options
);

使用已经创建的客户端。

在接受 Symfony 控制器方面,我无法发送文件:

var_dump($_FILES); // array(0) {}
var_dump($_POST);  // array(0) {}
var_dump(count($request->files->all())); // int(0)

然而,这两者:

var_dump(file_get_contents("php://input"));
var_dump($request->getContent());

在输入流上返回数据:

/myPath/FileController.php:xx:
string(601) "--e55f849feb078da4a9e35ba77da3ded02ec813a7
Content-Disposition: form-data; name="filename-0"; filename="filename-0"
Content-Length: 43

This is a testfile...
--e55f849feb078da4a9e35ba77da3ded02ec813a7
Content-Disposition: form-data; name="filename-1"; filename="filename-1"
Content-Length: 43

This is a testfile...
--e55f849feb078da4a9e35ba77da3ded02ec813a7
Content-Disposition: form-data; name="filename-2"; filename="filename-2"
Content-Length: 43

This is a testfile...
--e55f849feb078da4a9e35ba77da3ded02ec813a7--
"

如何以Symfony方式进入接收控制器?

需要考虑的好奇心:控制器报告

var_dump($request->getContentType()); // NULL

我的直觉告诉我这可能很重要。

共有2个答案

薛望
2023-03-14

这段代码对我有用。我认为您的API正在接收一个名为file的var类型数组。

$fopen=fopen("/etc/file.txt");//verify that file exists
$fopen2=fopen("/etc/file.txt");//verify that file exists

$apiRequest = $client->request('POST', 'http://xxx.xx.xxx.xx/upload/1/9', 
      [
      'multipart' => [
          [
            'name'     => 'file[]',
            'contents' => $fopen
          ],
          [
            'name'     => 'file[]',
            'contents' => $fopen2              
          ]
        ]
      ]);
        $response = json_decode($apiRequest->getBody());

dd($response);
聂华翰
2023-03-14

使用多部分选项时,不得自行指定“内容类型”标头。Guzzle 将负责处理这个问题,对于这个问题来说,更重要的是,负责分隔原始请求正文中的内容部分的边界。主内容类型标头定义该边界,如下所示:

Content-Type: multipart/form-data; boundary=unique-string-that-is-hopefully-not-used-in-the-real-content-because-it-separates-the-content-parts`

检查客户。php#L308:Guzzle在使用<code>multipart</code>选项时,将请求主体创建为<code>GuzzleHttp\Psr7\MultipartStream</code>对象。

然后检查MultipartStream的MultipartStream构造函数。php#L30:创建一个随机值用作边界:sha1(uniqid('',true))

然后,Guzzle将使用该边界在Client.php#L383上自行设置正确的内容类型。

但由于Guzzle没有覆盖您明确指定的选项,因此主标题指定了一个空边界,原始身体部位将由MultpartStream构造函数创建的边界分隔。在接收端,PHP无法再分离内容部分。

此代码适用于我:

(new GuzzleHttp\Client())->request(
    'POST',
    'http://localhost/upload',
    [
        'multipart' => [
            [
                'name' => 'filename-0',
                'contents' => fopen(__DIR__.'/sample-0.txt', 'rb'),
                'filename' => 'filename-0',
            ],
            [
                'name' => 'filename-1',
                'contents' => fopen(__DIR__.'/sample-1.txt', 'rb'),
                'filename' => 'filename-1',
            ],
            [
                'name' => 'filename-2',
                'contents' => fopen(__DIR__.'/sample-2.txt', 'rb'),
                'filename' => 'filename-2',
            ],
        ],
        'headers' => [
            # Do not override the Content-Type header here, Guzzle takes care of it
        ] ,
    ]
);

请注意,所有这些都与Symfony无关,即Symfony只是从它可以通过PHP的本地资源(如< code>$_FILES 、< code>$_POST等)获得的内容创建了它的< code>Request对象。您能够看到原始请求正文中的所有内容(< code>$request-

 类似资料:
  • 我有一个多文件上传表单: 我用ajax发布这些文件。我想一个接一个地上传选定的文件(为了创建单独的进度条,出于好奇)。 我可以通过以下方式获得文件列表或单个文件: 耶林 但是FileList是不可变的,我不知道如何提交单个文件。 我认为这是可能的,正如我所看到的http://blueimp.github.com/jQuery-File-Upload/.我不想使用这个插件,因为它与学习和结果一样重要

  • 本文向大家介绍Angular Js文件上传之form-data,包括了Angular Js文件上传之form-data的使用技巧和注意事项,需要的朋友参考一下 前言:很久没更新博客,最近公司pc端技术选型用angular,这几天就赶鸭子上架,硬着头皮直接上手angular。其中有许多小坑陆陆续续踩起走。今天就遇到一个比较常见的问题:图片上传。 主题:图片上传服务器,然后通过服务器传阿里云。 不废话

  • 我有一个远程服务A来上传文件。我有服务B,它通过FeignClient调用服务A的上传API来上传文件 服务 A 中的方法定义类似于 服务B中的方法是 我收到错误Content-Type“multipart/form data”not set for the request body of Type StandardMultipartFile 我已经尝试了https://github . com/

  • 我今天有一个非常烦人的问题。我在Macbook Pro上,PhpStorm 2017.3.6。 我试图创建一个简单的Symfony 4联系人表单,但PhpStorm出现了问题,“联系人类型”类根本无法识别。我已经尝试: < li >清除PhpStorm缓存并使其无效 < li >清除Symfony缓存 < li >重新启动Macbook < li >已将PhpStorm更新至2017.3.6 我还

  • 我对通过编程(通过HTTP POST或PUT请求)将文件(在我的例子中是图像或pdf)上传到Django应用程序的过程感到非常困惑。我读过医生的报告,但我必须承认它没有帮我度过难关。最让我困惑的是模板(和表单):为什么我需要在视图中指定模板和表单? 我只想将一个文件发送到一个目录,我想知道在Django部分和请求部分(内容类型…?)上执行此操作需要什么 我真的很感激任何人能在这里给我指明方向...

  • 问题内容: 我正在尝试使用伪装完成多部分文件上传,但似乎在任何地方都找不到很好的示例。我本质上希望HTTP请求类似于以下内容: 甚至… 我是否需要手动构建请求主体,包括生成多部分边界?考虑到此客户端可以执行的其他所有操作,这似乎有点过头了。 问题答案: 不,你没有。您只需要定义一种代理接口方法,将content-type指定为:multipart / form- data和其他信息,例如远程API