30

I am able to upload a file to an API endpoint using Postman.

I am trying to translate that into uploading a file from a form, uploading it using Laravel and posting to the endpoint using Guzzle 6.

Screenshot of how it looks in Postman (I purposely left out the POST URL) enter image description here

Below is the text it generates when you click the "Generate Code" link in POSTMAN:

POST /api/file-submissions HTTP/1.1
Host: strippedhostname.com
Authorization: Basic 340r9iu34ontoeioir
Cache-Control: no-cache
Postman-Token: 6e0c3123-c07c-ce54-8ba1-0a1a402b53f1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="FileContents"; filename=""
Content-Type: 


----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="FileInfo"

{ "name": "_aaaa.txt", "clientNumber": "102425", "type": "Writeoff" }
----WebKitFormBoundary7MA4YWxkTrZu0gW

Below is controller function for saving the file and other info. The file uploads correctly, I am able to get the file info.

I think the problem I am having is setting the multipart and headers array with the correct data.

public function fileUploadPost(Request $request)
{
    $data_posted = $request->input();
    $endpoint = "/file-submissions";
    $response = array();
    $file = $request->file('filename');
    $name = time() . '_' . $file->getClientOriginalName();
    $path = base_path() .'/public_html/documents/';

    $resource = fopen($file,"r") or die("File upload Problems");

    $file->move($path, $name);

    // { "name": "test_upload.txt", "clientNumber": "102425", "type": "Writeoff" }
    $fileinfo = array(
        'name'          =>  $name,
        'clientNumber'  =>  "102425",
        'type'          =>  'Writeoff',
    );

    $client = new \GuzzleHttp\Client();

    $res = $client->request('POST', $this->base_api . $endpoint, [
        'auth' => [env('API_USERNAME'), env('API_PASSWORD')],
        'multipart' => [
            [
                'name'  =>  $name,
                'FileContents'  => fopen($path . $name, 'r'),
                'contents'      => fopen($path . $name, 'r'),
                'FileInfo'      => json_encode($fileinfo),
                'headers'       =>  [
                    'Content-Type' => 'text/plain',
                    'Content-Disposition'   => 'form-data; name="FileContents"; filename="'. $name .'"',
                ],
                // 'contents' => $resource,
            ]
        ],
    ]);

    if($res->getStatusCode() != 200) exit("Something happened, could not retrieve data");

    $response = json_decode($res->getBody());

    var_dump($response);
    exit();
}

The error I am receiving, screenshot of how it displays using Laravel's debugging view:

enter image description here

4

3 回答 3

70

您发布数据的方式是错误的,因此接收到的数据格式不正确。

Guzzle 文档

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

name: (string, required) 表单域名称

contents:(StreamInterface/resource/string, required) 在表单元素中使用的数据。

headers: (array) 与表单元素一起使用的自定义标题的可选关联数组。

filename: (string) 作为文件名发送的可选字符串。

使用上面列表中的键并设置不必要的标头而不将每个字段分成一个数组将导致发出错误的请求。

$res = $client->request('POST', $this->base_api . $endpoint, [
    'auth'      => [ env('API_USERNAME'), env('API_PASSWORD') ],
    'multipart' => [
        [
            'name'     => 'FileContents',
            'contents' => file_get_contents($path . $name),
            'filename' => $name
        ],
        [
            'name'     => 'FileInfo',
            'contents' => json_encode($fileinfo)
        ]
    ],
]);
于 2016-07-11T13:12:17.960 回答
3
$body = fopen('/path/to/file', 'r');
$r = $client->request('POST', 'http://httpbin.org/post', ['body' => $body]);

http://docs.guzzlephp.org/en/latest/quickstart.html?highlight=file

于 2018-02-05T12:37:24.607 回答
0

在带有 guzzle 的 Laravel 8 中,我正在使用这个:

这个想法是您正在使用 fread 或 file_get_content 读取文件,然后您可以使用指向 /tmp 中的文件的 Laravel getPathname()

        $response = $this
            ->apiClient
            ->setUserKey($userToken)
            ->post(
                '/some/url/to/api',
                [
                    'multipart' => [
                        'name'     => 'avatar',
                        'contents' => file_get_contents($request->file('avatar')->getPathname()),
                        'filename' => 'avata.' . $request->file('avatar')->getClientOriginalExtension()
                    ]
                ]
            );
于 2021-12-09T14:58:33.680 回答