Подтвердить что ты не робот

Laravel - отображать PDF файл в хранилище без принудительной загрузки?

У меня есть файл PDF, хранящийся в app/storage/, и я хочу, чтобы пользователи, прошедшие проверку подлинности, могли просматривать этот файл. Я знаю, что я могу заставить их загрузить его с помощью

return Response::download($path, $filename, $headers);

но мне было интересно, есть ли способ заставить их просматривать файл непосредственно в браузере, например, когда они используют Google Chrome со встроенным средством просмотра PDF. Любая помощь будет оценена!

4b9b3361

Ответ 1

Обновление на 2017 год

Начиная с Laravel 5.2, описанного в разделе " Другие типы ответов", теперь вы можете использовать помощник по файлам для отображения файла в браузере пользователя.

return response()->file($pathToFile);

return response()->file($pathToFile, $headers);

Источник/спасибо ниже ответ

Устаревший ответ с 2014 года

Вам просто нужно отправить содержимое файла в браузер и сообщить ему тип содержимого, а не сказать браузеру загрузить его.

$filename = 'test.pdf';
$path = storage_path($filename);

return Response::make(file_get_contents($path), 200, [
    'Content-Type' => 'application/pdf',
    'Content-Disposition' => 'inline; filename="'.$filename.'"'
]);

Если вы используете Response::download он автоматически устанавливает Content-Disposition во вложение, что заставляет браузер загружать его. Посмотрите этот вопрос, чтобы узнать о различиях между встроенным Content-Disposition и вложением.

Изменение: В соответствии с запросом в комментариях, я должен указать, что вам нужно будет use Response в начале вашего файла, чтобы использовать Фасад.

use Response;

Или полностью определенное пространство имен, если Response не наложен на Illuminate Response Facade.

Ответ 2

С Laravel 5.2 вы можете использовать Ответные файлы
В принципе вы можете назвать это следующим образом:

return response()->file($pathToFile);

и он будет отображать файлы в формате PDF и изображения, встроенные в браузер.

Ответ 3

В Laravel 5.5 вы можете просто передать " inline" в качестве параметра удаления функции загрузки:

return response()->download('/path/to/file.pdf', 'example.pdf', [], 'inline');

Ответ 4

Я использую Laravel 5.4 и response()->file('path/to/file.ext') для открытия, например. pdf в встроенном режиме в браузерах. Это работает очень хорошо, но когда пользователь хочет сохранить файл, диалог сохранения предлагает последнюю часть URL-адреса в качестве имени файла.

Я уже пробовал добавить массив заголовков, как упоминается в Laravel-docs, но это, похоже, не отменяет заголовок, заданный с помощью файла() - method:

return response()->file('path/to/file.ext', [
  'Content-Disposition' => 'inline; filename="'. $fileNameFromDb .'"'
]);

Ответ 5

Ответ Бен Свинберн абсолютно прав - он заслуживает очков! Для меня, хотя ответ остался немного болтающимся в Laravel 5.1, который заставил меня исследовать - и в 5.2 (который вдохновил этот ответ) появился новый способ сделать это быстро.

Примечание. Этот ответ содержит подсказки для поддержки имен файлов UTF-8, но рекомендуется учитывать поддержку кросс-платформенной!

В Laravel 5.2 вы можете сделать это:

$pathToFile = '/documents/filename.pdf'; // or txt etc.

// when the file name (display name) is decided by the name in storage,
// remember to make sure your server can store your file name characters in the first place (!)
// then encode to respect RFC 6266 on output through content-disposition
$fileNameFromStorage = rawurlencode(basename($pathToFile));

// otherwise, if the file in storage has a hashed file name (recommended)
// and the display name comes from your DB and will tend to be UTF-8
// encode to respect RFC 6266 on output through content-disposition
$fileNameFromDatabase = rawurlencode('пожалуйста.pdf');

// Storage facade path is relative to the root directory
// Defined as "storage/app" in your configuration by default
// Remember to import Illuminate\Support\Facades\Storage
return response()->file(storage_path($pathToFile), [
    'Content-Disposition' => str_replace('%name', $fileNameFromDatabase, "inline; filename=\"%name\"; filename*=utf-8''%name"),
    'Content-Type'        => Storage::getMimeType($pathToFile), // e.g. 'application/pdf', 'text/plain' etc.
]);

И в Laravel 5.1 вы можете добавить выше метод response()->file() в качестве резервной копии через поставщика услуг с макросом ответа в методе загрузки (не забудьте зарегистрировать его, используя его пространство имен в config/app.php, если вы сделаете его классом). Содержимое загрузочного метода:

// Be aware that I excluded the Storage::exists() and / or try{}catch(){}
$factory->macro('file', function ($pathToFile, array $userHeaders = []) use ($factory) {

    // Storage facade path is relative to the root directory
    // Defined as "storage/app" in your configuration by default
    // Remember to import Illuminate\Support\Facades\Storage
    $storagePath         = str_ireplace('app/', '', $pathToFile); // 'app/' may change if different in your configuration
    $fileContents        = Storage::get($storagePath);
    $fileMimeType        = Storage::getMimeType($storagePath); // e.g. 'application/pdf', 'text/plain' etc.
    $fileNameFromStorage = basename($pathToFile); // strips the path and returns filename with extension

    $headers = array_merge([
        'Content-Disposition' => str_replace('%name', $fileNameFromStorage, "inline; filename=\"%name\"; filename*=utf-8''%name"),
        'Content-Length'      => strlen($fileContents), // mb_strlen() in some cases?
        'Content-Type'        => $fileMimeType,
    ], $userHeaders);

    return $factory->make($fileContents, 200, $headers);
});

Некоторые из вас не любят Laravel Facades или Helper Methods, но этот выбор за вами. Это должно дать вам указатели, если ответ Ben Swinburne не работает для вас.

Мнение: вы не должны хранить файлы в БД. Тем не менее, этот ответ будет работать, только если вы удалите части фасада Storage, взяв содержимое вместо пути в качестве первого параметра, как с ответом @BenSwinburne.

Ответ 6

Ответ Бен Свинберн был настолько полезен.

Код ниже для тех, у кого есть файл PDF в базе данных, такой как я.

$pdf = DB::table('exportfiles')->select('pdf')->where('user_id', $user_id)->first();

return Response::make(base64_decode( $pdf->pdf), 200, [
    'Content-Type' => 'application/pdf',
    'Content-Disposition' => 'inline; filename="'.$filename.'"',
]);

Где $pdf->pdf - столбец файлов в базе данных.

Ответ 7

Начиная с laravel 5.5, если файл хранится на удаленном хранилище

return Storage::response($path_to_file);

или, если он хранится локально, вы также можете использовать

return response()->file($path_to_file);

Я бы порекомендовал использовать фасад для хранения.

Ответ 8

Получение файлов
$contents = Storage::get('file.jpg');

Загрузка файлов
return Storage::download('file.jpg');

URL файлов
$url = Storage::url('file.jpg');