Laravel - отображать PDF файл в хранилище без принудительной загрузки?
У меня есть файл PDF, хранящийся в app/storage/, и я хочу, чтобы пользователи, прошедшие проверку подлинности, могли просматривать этот файл. Я знаю, что я могу заставить их загрузить его с помощью
return Response::download($path, $filename, $headers);
но мне было интересно, есть ли способ заставить их просматривать файл непосредственно в браузере, например, когда они используют Google Chrome со встроенным средством просмотра PDF. Любая помощь будет оценена!
Ответы
Ответ 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');