Загрузка файла с api-route, Laravel

112
28 января 2021, 12:50

Всем привет. Есть такая схема сайта: интерфейс пользователя(он же фронт) -=> back-end этого фронта -=> api.

Пользователю нужно скачать большой файл(прим.ссылки http://domain/api/123.iso). api требует в заголовках ключ клиента, который является приватным.

Код загрузки файла со стороны api:

$headers = array(
            'Content-Description'       => 'File Transfer',
            'Content-Type'              => File::mimeType($path),
            'Content-Transfer-Encoding' => 'binary',
            'Expires'                   => 0,
            'Cache-Control'             => 'must-revalidate, post-check=0, pre-check=0',
            'Pragma'                    => 'public',
            'Content-Length'            => File::size($path),
            'Content-Disposition'       =>  'attachment; filename="'.$name.'"'
        );
        $response = new Response('', 200, $headers);
        $response->sendHeaders();
        if(ob_start()) ob_end_clean();
        if ($fp = fopen($path, 'rb')) {
            while(!feof($fp)) {
                print(fread($fp, 8192));
                flush();
            }
            fclose($fp);
        }
        exit;

Как мне организовать приём этого ответа со стороны backend и отдать пользователю?

P.S. Идеи которые приходили в голову.

  1. Скачивание должно происходить при отправке формы(прямой переход) на адрес(http://domain/api/downloads/{filename}). Соответственно, контроллер Downloads будет отдавать {filename}. Зачем форма - что-бы установить ключ в отдельный input. Но это противоречит тому, что ключ api приватный, ведь можно посмотреть что было отправлено.

  2. Танцы с бубном. Код загрузчика на backend:

    $options = array(
       'http' => [
           'method' => 'GET',
           'header' => 'x-api: '.env('API_KEY')
       ]
    );
    $context = stream_context_create($options);
    $file = fopen(env('API_URL').'/library/test/download', 'r', false, $context);
    $headers = stream_get_meta_data($file);
    //decode header 'base-headers' to array, format 'base-header: {json_string}'
    $h = (array)json_decode(str_replace('base-headers:', '', $headers['wrapper_data'][3]));
    $response = new Response('', 200, $h);
    $response->sendHeaders();
    while(!feof($file)) {
        print(fread($file, 8192));
    }
    fclose($file);
    exit;
    

    Код обработки на api прежний, кроме заголовка:

    $headers = array(
        'Content-Description'       => 'File Transfer',
        'Content-Type'              => File::mimeType($path),
        'Content-Transfer-Encoding' => 'binary',
        'Expires'                   => 0,
        'Cache-Control'             => 'must-revalidate, post-check=0, pre-check=0',
        'Pragma'                    => 'public',
        'Content-Length'            => File::size($path),
        'Content-Disposition'       =>  'attachment; filename="'.$name.'"'
    );
    //$response = new Response('', 200, $headers);
    $h = [
       'base-headers' => json_encode($headers)
    ];
     $response = new Response('', 200, $h);
    

    При таком раскладе ОЗУ забивается в арифметической прогрессии - 1 загрузка(1,5 GB) ~ 30 Mb, что не есть хорошо.

Прошу Вашей помощи и подсказок в этом направлении.

READ ALSO
Как используется hashCode в HashSet/HashMap?

Как используется hashCode в HashSet/HashMap?

В лекции JavaRush «Реализации интерфейса Set, Queue» говорится следующее:

114
StateMachine и ожидание выполнения

StateMachine и ожидание выполнения

Согласно ТЗ, мне необходимо реализовать управление движущимся объектом с периодическими паузами в 2 секунды между каждым выполняемым действиемПри...

115
HashMap и его внутренности

HashMap и его внутренности

HashMap - структура данных для хранения связанных вместе пар "ключ-значение", применяется для использования хеш-таблицыБыл специально разработан...

143