Я новичок в Laravel и пытаюсь хранить личные изображения, чтобы только аутентифицированные пользователи могли получить к ним доступ. Сначала я сохранил изображения в папке Public/UserImages. Но здесь все изображения доступны и для неавторизованных пользователей, перейдя в «Проверить элемент хрома» и затем изменив идентификаторы пользователей. Будь добр, помоги мне...
Как работать с личными изображениями в laravel 5?
Ответы (4)
Это действительно зависит от вас. Он должен находиться за пределами каталога public — я бы лично выбрал resources/uploads или storage/uploads или полностью сохранил их за пределами сервера, используя поддержка облачной файловой системы.
Что бы вы ни выбрали, вам понадобится маршрут, который извлекает файл и передает его пользователю после первой проверки наличия у него доступа.
Ниже показано, как я решил проблему хранения изображений в Laravel 5 таким образом, чтобы только аутентифицированные пользователи могли просматривать изображения. Пользователи, не прошедшие проверку подлинности, будут перенаправлены на страницу входа. Мой сервер — это сервер Ubuntu/Apache2.
Создайте каталог /var/www/ВАШ ВЕБ-САЙТ/app/Assets/Images
Добавьте маршрут в app/Http/routes.php.
Route::get('/images/{file}','ImageController@getImage');Создайте приложение контроллера/Http/Controllers/ImageController.php
<?php namespace App\Http\Controllers; use App\Http\Requests; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Auth; class ImageController extends Controller { public function __construct() { $this->middleware('auth'); } public function getImage($filename) { $path = '/var/www/YOURWEBSITE/app/Assets/Images/'.$filename; $type = "image/jpeg"; header('Content-Type:'.$type); header('Content-Length: ' . filesize($path)); readfile($path); } }На ваш взгляд, у вас есть теги img, которые имеют:
src="{{ url('/images/test.jpg') }}"
Это, конечно, предполагает, что test.jpg является файлом в /var/www/ВАШ ВЕБ-САЙТ/приложение/Активы/Изображения/
Конечно, вы можете добавить больше логики, например, не указывать жестко путь к изображениям и т. д. Это всего лишь простой пример принудительной проверки подлинности. Обратите внимание на использование промежуточного программного обеспечения ('auth') в конструкторе контроллера.
У меня возникла такая же проблема несколько дней назад, и я придумал это решение:
Первое, что вам нужно сделать, это загрузить файл в закрытый каталог. Мое приложение хранит отсканированные счета-фактуры, поэтому я собираюсь поместить их в
storage/app/invoices. Код для загрузки файла и создания URL-адреса будет таким:// This goes inside your controller method handling the POST request. $path = $request->file('invoice')->store('invoices'); $url = env('APP_URL') . Illuminate\Support\Facades\Storage::url($path);Возвращаемый URL-адрес должен выглядеть примерно так: http://yourdomain.com/storage/invoices/uniquefilename.jpg
Теперь вам нужно создать контроллер, который использует
auth middlewareдля проверки подлинности пользователя. Затем определите метод, который извлекает файл из частного каталога и возвращает его в качестве ответа файла. Это было бы:<?php namespace App\Http\Controllers; use Illuminate\Support\Facades\Storage; class FileController extends Controller { public function __construct() { $this->middleware('auth'); } public function __invoke($file_path) { if (!Storage::disk('local')->exists($file_path)) { abort(404); } $local_path = config('filesystems.disks.local.root') . DIRECTORY_SEPARATOR . $file_path; return response()->file($local_path); } }Последнее, что нужно сделать, это зарегистрировать маршрут в файле
routes/web.php:Route::get('/storage/{file_name}', 'FileController')->where(['file_name' => '.*'])
Итак, у вас есть довольно многоразовый фрагмент для всех ваших проектов, связанных с личными файлами :)
Вот как это сделать в Laravel 5.7
Чтобы иметь личные файлы (изображения), вам необходимо обслуживать файлы через поток route => controller. И ваше промежуточное ПО аутентификации будет обрабатывать аутентификацию и разрешение. Если требуется дополнительная авторизация, вы обрабатываете ее в контроллере.
Итак, сначала мы устанавливаем маршрут:
Здесь у нас может быть один маршрут, который обрабатывает все наши файлы [лично я этого не предпочитаю]. Мы можем сделать это, используя такой маршрут (это как подстановочный знак).
Route::get('/storage/{filePath}', 'FileController@fileStorageServe')
->where(['filePath' => '.*'])
Вы также можете назвать это так:
Route::get('/storage/{fileName}', 'FileController@fileStorageServe')
->where(['fileName' => '.*'])->name('storage.gallery.file');
В противном случае мы создаем маршрут для каждого типа/категории файлов: (преимущество: вы сможете лучше контролировать доступность. (Каждый маршрут и тип ресурсов и его правила. Если вы хотите добиться этого с помощью маршрута с подстановочными знаками (позвольте мне назвать его так), вам нужно иметь условные блоки (если иначе, обрабатывать все разные ситуации. Это ненужные операции [идущие прямо вправо block, когда маршруты лучше разделены, плюс ко всему это позволяет лучше организовать обработку разрешений]).
Route::get('/storage/gallery/{file}', 'System\FileController@getGalleryImage')
->name('storage.gallery.image');
Наши маршруты были установлены СЕЙЧАС. Контроллер/Контроллеры
Подстановочный знак
<?php
public function fileStorageServe($file) {
// know you can have a mapping so you dont keep the sme names as in local (you can not precsise the same structor as the storage, you can do anything)
// any permission handling or anything else
// we check for the existing of the file
if (!Storage::disk('local')->exists($filePath)){ // note that disk()->exists() expect a relative path, from your disk root path. so in our example we pass directly the path (/.../laravelProject/storage/app) is the default one (referenced with the helper storage_path('app')
abort('404'); // we redirect to 404 page if it doesn't exist
}
//file exist let serve it
// if there is parameters [you can change the files, depending on them. ex serving different content to different regions, or to mobile and desktop ...etc] // repetitive things can be handled through helpers [make helpers]
return response()->file(storage_path('app'.DIRECTORY_SEPARATOR.($filePath))); // the response()->file() will add the necessary headers in our place (no headers are needed to be provided for images (it's done automatically) expected hearder is of form => ['Content-Type' => 'image/png'];
// big note here don't use Storage::url() // it's not working correctly.
}
Один на маршрут
(большая разница, это параметр, теперь он ссылается только на имя файла, а не на относительный путь к корню диска хранилища)
<?php
public function getCompaniesLogo($file) {
// know you can have a mapping so you dont keep the sme names as in local (you can not precsise the same structor as the storage, you can do anything)
// any permission handling or anything else
$filePath = config('fs.gallery').DIRECTORY_SEPARATOR.$file; // here in place of just using 'gallery', i'm setting it in a config file
// here i'm getting only the path from the root (this way we can change the root later) / also we can change the structor on the store itself, change in one place config.fs.
// $filePath = Storage::url($file); <== this doesn't work don't use
// check for existance
if (!Storage::disk('local')->exists($file)){ // as mentionned precise relatively to storage disk root (this one work well not like Storage:url()
abort('404');
}
// if there is parameters [you can change the files, depending on them. ex serving different content to different regions, or to mobile and desktop ...etc] // repetitive things can be handled through helpers [make helpers]
return response()->file(storage_path('app'.DIRECTORY_SEPARATOR.($file))); // the response()->file() will add the necessary headers in our place
}
Теперь вы можете проверить, сформировав правильный URL-адрес (перейдите в хранилище, скопируйте имя файла и сформируйте свой маршрут. Он должен показать вам изображение)
Осталось последнее:
Как показать это в поле зрения
подстановочный знак
<img src="{{route('routeName', ['fileParam' => $storageRelativePath])}}" />
Обратите внимание, что routeName здесь, в приведенном выше примере, будет storage.file, а fileParam будет filePath. $storageRelativePath например, вы получаете из базы данных (обычно это то, что будет).
За маршрут
<img src="{{route('routeName', ['fileName' => basename($storageRelativePath)])}}" />
То же самое, но мы предоставляем только имя файла.
Примечания. Лучший способ отправить такой ответ — использовать response()->file();. То, что вы найдете в документе 5.7. Эта производительность мудра против Image::make($storagePath)->response();. Если вам не нужно изменять его на лету.
Вы можете проверить мою статью в среде: https://medium.com/@allalmohamedlamine/how-to-serve-images-and-files-privatly-in-laravel-5-7-a4b469f0f706