Загрузить файл с помощью Guzzle 6 в конечную точку API

Я могу загрузить файл в конечную точку API с помощью Postman.

Я пытаюсь перевести это на загрузку файла из формы, загрузку его с помощью Laravel и отправку в конечную точку с помощью Guzzle 6.

Скриншот того, как это выглядит в Postman (я намеренно пропустил URL POST)  введите описание изображения здесь

Ниже приведен текст, который генерируется при нажатии на ссылку «Создать код» в 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

Ниже представлена ​​функция контроллера для сохранения файла и другой информации. Файл загружается правильно, я могу получить информацию о файле.

Я думаю, что проблема, с которой я столкнулся, заключается в настройке массива multipart и headers с правильными данными.

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();
}

Ошибка, которую я получаю, снимок экрана, показывающий, как она отображается в режиме отладки Laravel:

введите описание изображения здесь


person Brad    schedule 30.06.2016    source источник


Ответы (2)


Вы отправляете данные неправильно, поэтому полученные данные искажены.

Жрать документы:

Значение multipart - это массив ассоциативных массивов, каждый из которых содержит следующие пары ключ-значение:

name: (обязательная строка) имя поля формы

_3 _ :( StreamInterface / resource / string, обязательно) Данные для использования в элементе формы.

headers: (array) Необязательный ассоциативный массив настраиваемых заголовков для использования с элементом формы.

filename: (строка) Необязательная строка для отправки в качестве имени файла в части.

Использование ключей из приведенного выше списка и установка ненужных заголовков без разделения каждого поля на один массив приведет к неправильному запросу.

$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)
        ]
    ],
]);
person revo    schedule 11.07.2016
comment
указанное выше решение работает, когда я не добавляю filename '= ›$ name в качестве аргумента. Когда я добавляю имя файла, ничего не отправляется. - person Aditya Joshi; 14.08.2018
comment
Следует ли отправлять file_get_contents или fopen? - person zardilior; 27.11.2018
comment
@zardilior Как я посмотрел на функцию stream_for, определенную в пакете guzzlehttp/psr7, обе обрабатываются правильно. - person revo; 28.11.2018
comment
@AdityaJoshi в моем случае у меня это была двоичная строка, и она работала, только отправляя ее с именем файла и получая в laravel с запросом- ›имеет - person zardilior; 28.11.2018

$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

person Pawel    schedule 05.02.2018
comment
Пожалуйста, не размещайте только ответы с кодом. Добавьте текст для сопровождения вашего кода. - person rollstuhlfahrer; 05.02.2018
comment
То, что вы опубликовали, сработало для меня. docs.guzzlephp.org/en/latest/ - person andreshg112; 13.07.2018
comment
Это неправильный ответ, поскольку OP запросил многостраничную загрузку, но это все еще полезно. - person Akira Yamamoto; 22.01.2021
comment
Ссылка на документы очень полезна. - person mbomb007; 26.04.2021