使用 Guzzle 将数据和文件一起发布到 Laravel API

Posted

技术标签:

【中文标题】使用 Guzzle 将数据和文件一起发布到 Laravel API【英文标题】:Post data and file together to Laravel API using Guzzle 【发布时间】:2019-12-08 08:35:06 【问题描述】:

我有两个工作项目通过 Laravel 中内置的 API 相互通信。到目前为止,只有使用 GuzzleHttp 6 发出的简单 POST 请求。

我目前正在尝试从 1 到 2 发出一个新的 POST 请求,这将发送几个简单的字段和一个文件。 项目 1 有一个表单,在表单提交时我处理数据并希望通过对这个新 API 端点的 POST 请求将它们发送到项目 2。

我尝试了不同的 guzzle 选项“multipart”、“form_data”等,并意识到它们可能无法组合在一起。现在我明白了这个选项是排他的,并且只使用“多部分”似乎是要走的路。 但是当我向 Laravel 发送请求时,没有数据和文件。

这是我的请求的代码

$options = ‌[
  'multipart' => 
  [
    [
      'name' => 'data',
      'contents' => '"field_1":"Test","field_2":"Test","field_3":"Test"',
      'headers' => 
        [
            'Content-Type' => 'application/json',
        ],
    ],
    [
      'name' => 'file',
      'filename' => 'test.pdf',
      'Mime-Type' => 'application/pdf',
      'contents' => file_get_contents($_FILEs['text_file']['temp_name']),
    ]
  ]
];

$this->client->request('POST', "api/test_post", $options)

我也试了一下:

$options = ‌[
  'multipart' => 
  [
    [
      'name' => 'field_1',
      'contents' => 'Test',
    ],
    [
      'name' => 'field_2',
      'contents' => 'Test',
    ],
    [
      'name' => 'file',
      'filename' => 'test.pdf',
      'Mime-Type' => 'application/pdf',
      'contents' => fopen($_FILEs['text_file']['temp_name'],'r'),
    ]
  ]
];

$this->client->request('POST', "api/test_post", $options)

如果我在接收端查看请求内容,那里什么都没有。没有字段或文件。

我看过一些情侣帖子,有些人说要包含标题,有些人说不要。我有点迷路了,现在没有想法了。

我希望这些信息就像我猜想的那样:

$request->inpust('field_1') -> 'test' $request->inpust('field_2') -> 'test' $request->inpust('field_3') -> 'test' $request->file('file') -> 我上传的文件

另外我应该指出,我不确定 multipart/form-data 是如何工作的,所以这可能对我没有帮助。

如果你能指出正确的方向,那将很有帮助

【问题讨论】:

$_FILEs['text_file'] 不起作用,1)因为它应该是 $_FILES 和 2)因为如果使用正确,$_FILES['text_file'] 可能是一个数组,而不是文件的路径。如果您没有移动上传的文件,也许您的意思是 $_FILES['text_file']['tmp_name'] 是的,我的错,这只是我写问题时的一个错误,我实际上使用了 file_get_contents($_FILES['text_file']['tmp_name']) 正如你所说的 【参考方案1】:

好吧,我终于想通了。上面的第二个示例是要走的路也一定要检查请求的标头和客户端...

由于这个 API 已经运行了很长一段时间,并且只做 json 类型的请求,所以客户端被实例化了

$options = [
  headers => [ 'Content-Type' => 'application/json']
]

正如互联网上的多个答案所述,这会阻止 Guzzle 根据请求选项自动设置 Content-Type。

在我的情况下,删除此行使 Guzzle 能够在提供“多部分”选项时正确设置它。

此外,由于所有其他请求都使用 'json' 选项,Guzzle 也很神奇,并且还设置了 'Content-Type' => 'application/json'。

【讨论】:

以上是关于使用 Guzzle 将数据和文件一起发布到 Laravel API的主要内容,如果未能解决你的问题,请参考以下文章

将 Curl 客户端 ssl 移动到 Guzzle

使用 Guzzle PHP 将文件分块上传到 URL 端点

Guzzle 获取文件并转发

Guzzle 请求:发布正文数据

从 laravel 调用 HTTPS 请求到外部 API

使用 Guzzle 上传文件