使用 Guzzle 上传文件

Posted

技术标签:

【中文标题】使用 Guzzle 上传文件【英文标题】:Upload file using Guzzle 【发布时间】:2018-03-24 10:39:03 【问题描述】:

我有一个可以上传视频并将其发送到远程目的地的表单。我有一个 cURL 请求,我想使用 Guzzle 将其“翻译”为 php

到目前为止,我有这个:

public function upload(Request $request)
    
        $file     = $request->file('file');
        $fileName = $file->getClientOriginalName();
        $realPath = $file->getRealPath();

        $client   = new Client();
        $response = $client->request('POST', 'http://mydomain.de:8080/spots', [
            'multipart' => [
                [
                    'name'     => 'spotid',
                    'country'  => 'DE',
                    'contents' => file_get_contents($realPath),
                ],
                [
                    'type' => 'video/mp4',
                ],
            ],
        ]);

        dd($response);

    

这是我使用的 cURL,我想翻译成 PHP:

curl -X POST -F 'body="name":"Test","country":"Deutschland";type=application/json' -F 'file=@C:\Users\PROD\Downloads\617103.mp4;type= video/mp4 ' http://mydomain.de:8080/spots

所以当我上传视频时,我想替换这个硬编码

C:\Users\PROD\Downloads\617103.mp4.

当我运行这个时,我得到一个错误:

客户端错误:POST http://mydomain.de:8080/spots 导致 400 Bad Request 响应:请求正文无效:期望表单值“body”

客户端错误:POST http://mydomain.de/spots 导致 400 Bad Request 响应: 请求正文无效:期望表单值“正文”

【问题讨论】:

【参考方案1】:

我会查看 Guzzle 的 multipart 请求选项。我看到两个问题:

    JSON 数据需要进行字符串化,并使用您在 curl 请求中使用的相同名称进行传递(容易混淆的名称为 body)。

    curl 请求中的type 映射到标头Content-Type。来自$ man curl

    您还可以使用 'type=' 告诉 curl 使用什么 Content-Type。

尝试类似:

$response = $client->request('POST', 'http://mydomain.de:8080/spots', [
    'multipart' => [
        [
            'name'     => 'body',
            'contents' => json_encode(['name' => 'Test', 'country' => 'Deutschland']),
            'headers'  => ['Content-Type' => 'application/json']
        ],
        [
            'name'     => 'file',
            'contents' => fopen('617103.mp4', 'r'),
            'headers'  => ['Content-Type' => 'video/mp4']
        ],
    ],
]);

【讨论】:

【参考方案2】: 使用multipart 选项时,请确保您没有传递content-type => application/json :) 如果您想同时发布表单字段和上传文件,只需使用此multipart 选项。这是一个数组数组,其中name 是表单字段名称,它的值是发布的表单值。一个例子:
'multipart' => [
                [
                    'name' => 'attachments[]', // could also be `file` array
                    'contents' => $attachment->getContent(),
                    'filename' => 'dummy.png',
                ],
                [
                    'name' => 'username',
                    'contents' => $username
                ]
            ]

【讨论】:

以上是关于使用 Guzzle 上传文件的主要内容,如果未能解决你的问题,请参考以下文章

PHP 上传文件到其他服务器

PHP 使用 Guzzle 执行 HTTP 请求

PHP 使用 Guzzle 执行 HTTP 请求

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

PHP Guzzle接口请求库应用

Laravel Google api 客户端获取刷新令牌并上传文件