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

狂饮6:上传带有数组数据的文件

宗政兴发
2023-03-14

我必须使用文件发送数组数据。仅使用数据即可正常工作:

$client->post('http://xxx/', [
    'form_params' => [
        [
            'data' => ['id' => 1234, 'name' => 'nombre'],
            'valid' => true
        ]
    ]
]);

但是,既然我不能将“form_params”与“multipart”一起使用,那么如何发送带有数组和布尔数据的文件呢?

我试过了:

$client->post('http://xxx/', [
    'multipart' => [
        [
            'name'     => 'myfile',
            'contents' => fopen('my_file.txt', 'r'),
        ],
        [
            'name'     => 'data',
            'contents' => ['id' => 1234, 'name' => 'nombre'],
        ]
        [
            'name'     => 'valid',
            'contents' => true,
        ]
    ],
]);

但是我收到一个错误,因为“contents”不接受布尔值或数组值。

我需要一些帮助。

谢谢

更新:我无法解决这个问题,最后我不得不使用一个不太好的解决方案,包括作为查询字符串的表单文件参数并仅使用Multipart。类似于:

$client->post('http://xxx?id=1234&name=nombre', [
'multipart' => [
    [
        'name'     => 'myfile',
        'contents' => fopen('my_file.txt', 'r'),
    ],
],

]);

共有3个答案

巴博耘
2023-03-14

您可以使用递归方法获取数据数组并准备多部分数组:

private function prepareMultipartParams($params, $baseKey = null): array
{
    $result = [RequestOptions::MULTIPART => []];
    foreach ($params as $key => $value) {
        $key = $baseKey == null ? $key : "{$baseKey}[{$key}]";
        if (is_array($value))
            foreach ($this->prepareMultipartParams($value, $key) as $array)
                $result[RequestOptions::MULTIPART] = array_merge($result[RequestOptions::MULTIPART], $array);
        else
            $result[RequestOptions::MULTIPART][] = [
                'name' => $key,
                'contents' => $value instanceof UploadedFile ? fopen($value->path(), 'r+') : $value
            ];
    }

    return $result;
}
长孙硕
2023-03-14

有一个选项可以通过Guzzle一起发送上传文件和数组数据,但形式有所不同:

$client->post('http://xxx/', [
    'multipart' => [
        [
            'name'     => 'myfile',
            'contents' => fopen('my_file.txt', 'r'),
        ],
        [
            'name'     => 'data[0][id]',
            'contents' => 1234,
        ],
        [
            'name'     => 'data[0][name]',
            'contents' => 'nombre',
        ],
        [
            'name'     => 'data[1][id]',
            'contents' => 2222,
        ],
        [
            'name'     => 'data[1][name]',
            'contents' => 'nombre2',
        ],
        [
            'name'     => 'valid',
            'contents' => true,
        ]
    ],
]);

另一方面,你可以用 $_POST['data'] 获取数据,然后执行 foreach:

foreach ($_POST['data'] as $data) {
    echo "Id: ".$data['id'];
    echo "Name: ".$data['name'];
}
阳兴文
2023-03-14

根据Guzzle文档:

multipart的值是关联数组的数组,每个数组包含以下键值对:

  • 名称:(字符串,必填)表单字段名称
  • 内容:(StreamInterface/resource/string,必填)要在表单元素中使用的数据
  • headers:(数组)自定义标头的可选关联数组,用于表单元素
  • filename:(string)作为部件中的文件名发送的可选字符串

所以看起来它只接受内容的字符串(直接或作为流)。他们可能的理由是,因为这是一个多部分的表单,您应该分别发送每个数据点,如下所示...

$client->post('http://xxx/', [
    'multipart' => [
        [
            'name'     => 'myfile',
            'contents' => fopen('my_file.txt', 'r'),
        ],
        [
            'name'     => 'id',
            'contents' => '1234',
        ],
        [
            'name'     => 'name',
            'contents' => 'nombre',
        ],
        [
            'name'     => 'valid',
            'contents' => 'true',
        ]
    ],
]);

在不知道数据是如何被解析的情况下,我不能肯定地说这是一个可行的选择,但是因为它接受定制的头,所以您可以将它作为JSON数组(以字符串形式)发送,然后设置内容类型:

$client->post('http://xxx/', [
    'multipart' => [
        [
            'name'     => 'myfile',
            'contents' => fopen('my_file.txt', 'r'),
        ],
        [
            'name'     => 'data',
            'contents' => '{"id":1234, "name":"nombre"}',
            'headers'  => ['Content-Type' => 'text/x-json']
        ],
        [
            'name'     => 'valid',
            'contents' => 'true',
        ]
    ],
]);

另一种选择是直接使用cURL,尽管我相信您希望避免这种情况,因为您使用的是Guzz。

更新

这不是我亲自测试过的东西,但是这里有一个你可以尝试的东西...(其实我应该先想到这个的)。

$client->post('http://xxx/', [
    'multipart' => [
        [
            'name'     => 'myfile',
            'contents' => fopen('my_file.txt', 'r'),
        ],
        [
            'name'     => 'data',
            'contents' => 'id=1234&name=nombre',
            'headers'  => ['Content-Type' => 'text/plain; charset=ISO-8859-1']
        ],
        [
            'name'     => 'valid',
            'contents' => true,
        ]
    ],
]);
 类似资料:
  • 我想向Guzzle Http请求添加一些数据。有文件名、文件内容和带有授权密钥的头。 但我得到错误 可捕获的致命错误:传递给guzzle http \ PSR 7 \ multipart stream::add element()的参数2必须是数组类型,字符串给定,在vendor \ guzzle http \ PSR 7 \ src \ multipart stream . PHP的第70行调用

  • 我想使用cURL不仅以HTTP POST发送数据参数,而且还上传具有特定表单名称的文件。我该怎么做呢?

  • 我正试图使用阿拉莫菲尔上传文件。使用文件()时,上传效果很好,但是,我似乎不知道如何使用选项? 这是我的测试: 我的状态代码是415? 此外,如何在上传中发送其他参数? 谢啦 编辑 我没有设置正确的内容类型: 仍然不知道如何发送附加参数随上传。

  • 我在使用古斯的时候有奇怪的问题 当我试图模拟一个错误的请求(例如,返回状态码404的请求)时,Guzzle抛出一个ClientException,其中包含该请求失败的所有细节。 当我试图捕捉这个异常时,我的脚本退出,并带有一个致命的错误,说明我没有捕捉到异常,它显示了一个XDebug跟踪,说明我有一个内存泄漏。 我的代码如下所示: 注意:httpClient是GuzzleHttp/CLient的有

  • 我试图使用AlamoFire将图像(avatarImage)作为formData参数类型上载到服务器,但每次我尝试发布时都会生成一个“数据无法读取,因为它的格式不正确”错误。我不太清楚我做错了什么。 PS:我正在使用multipartFormData上载b/c,我还需要发送一些其他参数(一旦我能够上载图像)。

  • 问题内容: http://www.mkyong.com/webservices/jax-rs/file-upload-example-in- jersey/ 我正在遵循本指南并遇到问题。我有一些问题。 是否所有依赖项都必须对应?我的项目有一些org.glassfish.jersey依赖项,本指南建议使用org.sun.jersey。我是否也必须使用相同的版本进行更改? 我有这个错误 这是我的网络服