Печать html перед загрузкой zip-файла

sarah_jayne_11 спросил: 28 апреля 2018 в 08:29 в: php

Привет, коллеги-кодеры!

Я ищу решение для показа html-страницы, в то время как мой php-код подготавливает .zip, который затем загружается. Причина в том, что иногда молнии становятся все больше и требуют времени.

HTML-страница будет базовой: "Подождите, пока ваши .zip-файлы будут подготовлены". Стороной PHP является Symfony. Поэтому я вхожу в мою функцию getInboxExportAction, вызывая https://myapi.com/orders/orderid/inbox/export.

Функция загрузки (makeExportDownloadRequestResponse) работает нормально. Но если я добавлю флеш после выполнения моего $ response, .zip будет напечатан в html, а не загружен ...

public function getInboxExportAction(Request $request, $orderId)
{    $response = new Response($this->twig->render('base.html.twig',
            ['content' => '
            <h1>Download</h1>
            <p>Your zip is being prepared for download, please wait...</p>
        ']));
    $response->headers->set('Content-Type', 'text/html');
    //Here I would like to echo + flush my html. 
    //Then stop the flush and continue my code
    $receivedOrder = $this->fetchRequestedReceivedOrder($orderId);
    if (!$receivedOrder instanceof ReceivedOrder) {
        return $receivedOrder;
    }    if (!$receivedOrder->getSentorder()) {
        $this->makeErrorResponse('Sent order was not found', Response::HTTP_BAD_REQUEST);
    }    return $this->makeExportDownloadRequestResponse($receivedOrder->getSentorder(), $request->get('format'));}

Я также очень открыт для любых других идеи, кто-то должен был бы исправить эту проблему:)

Спасибо,

Изменить: функция My $ this- > makeExportDownloadRequestResponse () возвращает ответ, а не путь. Мы отсоединяем файл на сервере по причинам хранения.

 $content = file_get_contents($zipTmpFile);
 unlink($zipTmpFile);
 $response = new Response($content);
 $dispositionHeader = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT,
        'myFile_' . date('Y_m_d_h_i_s') . '.zip');
 $response->headers->set('Content-Disposition', $dispositionHeader);
 return $response;

Второе редактирование: я понимаю, что я пытаюсь сделать (изменить тип контента в течение одного вызова) нахмурился. В настоящее время я пытаюсь придумать более элегантное решение.

3 ответа

fxbt ответил: 28 апреля 2018 в 09:14

В getInboxExportAction просто верните ответ с текстом.

Затем в этом ответе добавьте тег <meta http-equiv="refresh" content="1;url=xxx">, чтобы перенаправить пользователя на другой действие, которое будет генерировать zip-файл.

Вы также можете обработать это перенаправление с помощью javascript.

Обратите внимание, что вы можете использовать StreamedResponse для обработки zip-загрузки: https://symfony.com/doc/current/components/http_foundation.html#streaming-a-response

sarah_jayne_11 ответил: 01 мая 2018 в 08:02
Спасибо за решение, которое звучит довольно изящно. Хотя я не мог использовать его в своем проекте, я сохраню это в другой раз.
vietanhyt ответил: 28 апреля 2018 в 09:27

Самое главное, что вы устанавливаете $response->headers->set('Content-Type', 'text/html');, браузер не будет загружать .zip-файл.

Если ваш метод makeExportDownloadRequestResponse может вернуть абсолют. zip file path (или вы можете вычислить его), вы можете попробовать:

public function getInboxExportAction(Request $request, $orderId)
{    $response = new Response($this->twig->render('base.html.twig',
            ['content' => '
            <h1>Download</h1>
            <p>Your zip is being prepared for download, please wait...</p>
        ']));
    $response->headers->set('Content-Type', 'text/html');
    //Here I would like to echo + flush my html. 
    //Then stop the flush and continue my code
    $receivedOrder = $this->fetchRequestedReceivedOrder($orderId);
    if (!$receivedOrder instanceof ReceivedOrder) {
        return $receivedOrder;
    }    if (!$receivedOrder->getSentorder()) {
        $this->makeErrorResponse('Sent order was not found', Response::HTTP_BAD_REQUEST);
    }    // prepare the to be downloaded zip file
    // then, do sth to get the .zip file path
    $zipFilePath = $this->makeExportDownloadRequestResponse($receivedOrder->getSentorder(), $request->get('format'));            // re-set header
    header('Content-Type: application/zip');
    header('Content-disposition: attachment; filename=whateverName.zip');
    header('Content-Length: ' . filesize($zipFilePath));
    readfile($zipFilePath);
}

Это позволит браузеру загружать zip-файл.

Наконец, если ваша функция работает как API, и для его выполнения нужен внешний интерфейс JS, попробуйте с классом Blob в JS.

Franck Gamess ответил: 28 апреля 2018 в 09:30

Вы действительно можете использовать StreamedResponse, чтобы избавиться от этой проблемы. О том, что весь файл .wip-файла отображается из-за флеша, попробуйте вызвать ob_flush до

sarah_jayne_11 ответил: 01 мая 2018 в 08:03
Я не мог изменить тип контента в StreamedResponse, но спасибо за представление :)