Symfony 3.4 — Передача файла потока API для загрузки на клиент

#php #download #stream #symfony-3.4 #guzzle6

#php #Скачать #поток #symfony-3.4 #guzzle6

Вопрос:

API отправляет мне поток, содержащий zip-архив из нескольких файлов, которые я выбираю, предоставляя их идентификаторы в параметре SelectedIds моего запроса. Я получаю ответ PSR7, который я передаю в HttpFoundationFactory, чтобы вернуть ответ, соответствующий тому, что должен вернуть контроллер Symfony.

(цель состоит в том, чтобы загрузить zip-файл в браузере на стороне клиента.)

Вот содержимое моего метода контроллера

 $client  = $this->getApiClient();
$user    = $this->getUser();
$idList  = [51,52,53];
$psr7ApiResponse = $client->post('/v1/get-zip', [
    'headers'     => [
        'Authorization' => sprintf('Bearer %s', $user->getToken()),
    ],
    'http_errors' => false,
    'json'        => [
        'SelectedIds' => $idList,
    ],
]);

$httpFoundationFactory = new HttpFoundationFactory();
return $httpFoundationFactory->createResponse($psr7ApiResponse);
 

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

Я протестировал API с помощью postman, и все в порядке; мой контроллер также отправляет мне обратно 200

Комментарии:

1. Вы пробовали устанавливать http_errors значение true на производстве?

2. да, ошибок нет, все в порядке:'(но ответ кажется пустым

3. Что внутри $psr7ApiResponse ? Он должен содержать код состояния и некоторые заголовки, которые, как мы надеемся, должны содержать больше информации. У вас полностью включены отчеты об ошибках в PHP?

4. У меня действительно нет ошибок, он работает очень хорошо локально, но не онлайн. Весь код состояния равен 200. Очень сложно отлаживать. похоже, что содержимое канала не полностью возвращается в мой серверный сервер, когда я переношу его в браузер

5. Существуют ли какие-либо другие функции в том же API, которые не загружают ZIP-файлы (например, простой GET или POST), которые вы можете протестировать на PROD, чтобы определить, является ли это проблемой с API в целом или изолировано для этого конкретного процесса? Если первое, также подтвердите, что ваша конечная точка API не имеет ограничений белого списка IP, запрещающих ей отправлять ответы вашего prod-сервера. И не могли бы вы опубликовать ответ внутри $psr7ApiResponse , пожалуйста.

Ответ №1:

Выполните следующие действия, чтобы устранить проблему:

1. Проверьте, является ли содержимое $psr7ApiResponse допустимым и правильным

Вы находитесь в другой среде. Возможно, по какой-то причине ваш серверный скрипт не получает действительного ответа. Возможно, аутентификация не работает. Распечатайте и отладьте полученный ответ в какой-нибудь файл журнала настолько подробно, насколько это необходимо (используйте регистраторы: https://symfony.com/doc/current/logging.html ).

Если содержимое или результирующий класс вызова неверны, проблема заключается в связи с удаленным вызовом, и вы должны отладить это. Скорее всего, это так.

2. Проверьте, действительно ли ваш клиент понимает ответ, и проверьте, правильный ли ответ

Ваш клиент определенно не должен получать пустую страницу (это указывает на то, что проблема равна 1).

Попробуйте явно вернуть файл с помощью SymfonyComponentHttpFoundationFileFile .

Вы также можете вручную задать определенные заголовки ZIP для Response объекта — по крайней мере, для отладки:

     // set example variables
    $filename = "zip-to-download.zip";
    $filepath = "/path"; // maybe save the response to a temp file for debugging purposes
    
    $response = $httpFoundationFactory->createResponse($psr7ApiResponse);
    $response->headers->set('Pragma','public');
    $response->headers->set('Expires',0);
    $response->headers->set('Cache-Control','must-revalidate, post-check=0, pre-check=0');
    $response->headers->set('Content-Description','File Transfer');
    $response->headers->set('Content-type','application/octet-stream');
    $response->headers->set('Content-Disposition','attachment; filename="'.$filename.'"');
    $response->headers->set('Content-Transfer-Encoding','binary');
    return $response;