Laravel 5 - Как получить доступ к изображению, загруженному в хранилище, в View?


172

Я загрузил аватары пользователя в хранилище Laravel. Как я могу получить к ним доступ и отобразить их в виде?

Сервер направляет все запросы /public, так как я могу показать их, если они находятся в /storageпапке?

Ответы:


349

Лучший подход заключается в создании символической ссылки , как @SlateEntropy очень хорошо указал в ответ ниже . Чтобы помочь с этим, начиная с версии 5.3, Laravel включает команду, которая делает это невероятно простым:

php artisan storage:link

Это создает символическую ссылку из public/storageк storage/app/publicвам и что все , что есть в ней. Теперь любой файл в /storage/app/publicможно получить по ссылке, например:

http://somedomain.com/storage/image.jpg

Если по какой-либо причине вы не можете создать символические ссылки (может быть, вы используете общий хостинг и т. Д.) Или вы хотите защитить некоторые файлы с помощью некоторой логики управления доступом, есть альтернатива иметь специальный маршрут, который читает и обслуживает изображение. Например, простой маршрут закрытия:

Route::get('storage/{filename}', function ($filename)
{
    $path = storage_path('public/' . $filename);

    if (!File::exists($path)) {
        abort(404);
    }

    $file = File::get($path);
    $type = File::mimeType($path);

    $response = Response::make($file, 200);
    $response->header("Content-Type", $type);

    return $response;
});

Теперь вы можете получить доступ к своим файлам так же, как если бы у вас была символическая ссылка:

http://somedomain.com/storage/image.jpg

Если вы используете библиотеку изображений Intervention, вы можете использовать ее встроенный responseметод, чтобы сделать вещи более лаконичными:

Route::get('storage/{filename}', function ($filename)
{
    return Image::make(storage_path('public/' . $filename))->response();
});

ПРЕДУПРЕЖДЕНИЕ

Имейте в виду, что, обслуживая файлы вручную , вы подвергаетесь снижению производительности , поскольку вы проходите весь жизненный цикл запроса Laravel, чтобы прочитать и отправить содержимое файла, что значительно медленнее, чем сервер HTTP обрабатывает его.


Это кажется хорошим. Я хотел бы задать еще один вопрос. Рекомендуется ли хранить такие файлы, как аватары, превью и т. Д. (Загруженные файлы от пользователей) в хранилище?
— Тадеаш Йилек,

5
Вы можете хранить их где угодно, но если это не личные файлы, я думаю, вам лучше хранить их в publicкаталоге. Таким образом, вы избежите накладных расходов, связанных с составлением ответа на изображение, который HTTP-сервер может обработать намного быстрее.
— Богдан

2
Лично я не буду хранить пользовательские файлы в общей папке, я нахожу вещи более аккуратными и более управляемыми, когда папка хранения используется для хранения.
— SlateEntropy

2
Я бы не рекомендовал ни один из них, потому что тогда вы добавляете накладные расходы на загрузку Laravel снова и / или используете PHP для чтения каждого изображения. Использование символической ссылки, как описано в CmdSft, будет намного быстрее.
— user1960364

4
@ user1960364 Вот почему в последнем абзаце настоятельно рекомендуется использовать символическую ссылку. Но сам ответ, хотя и не является лучшим решением с точки зрения производительности, по-прежнему действителен и может быть единственным подходом для людей, запускающих приложения на общих серверах, где символические ссылки могут быть невозможны для настройки. Ответ также показывает, как вы можете обслуживать файлы программно, если когда-либо возникнет такая необходимость, возможно, для обслуживания зашифрованных файлов, как это задано в этом вопросе .
— Богдан

53

Одним из вариантов будет создание символической ссылки между подпапкой в ​​вашем каталоге хранения и публичным каталогом.

Например

ln -s /path/to/laravel/storage/avatars /path/to/laravel/public/avatars

Это также метод, используемый Envoyer , менеджером развертывания, созданным Taylor Otwell, разработчиком Laravel.


Я немного новичок в этом. Это нужно запустить на терминале или определить в файле конфигурации где-нибудь в laravel?
— Гаурав Мехта

да, вам нужно запустить это через командную строку. Он должен быть настроен везде, где вы развернете приложение.
— SlateEntropy

Для пользователей Windows есть отдельный инструмент для этого, если вы не хотите использовать CMD: github.com/amd989/Symlinker#downloads
— David

3
Был задан вопрос, как показать storageпубличные аватары пользователей , обычно аватары не требуют какого-либо контроля доступа. Если никакой безопасности не требуется, используя какое-либо промежуточное программное обеспечение или маршрут, это просто потерянный удар по вашим ресурсам. Стоит также отметить, что в Laravel 5.2 существует отдельный файл «диск» для открытых файлов ( laravel.com/docs/5.2/filesystem ), использующий символические ссылки .
— SlateEntropy

6
Для этого в Laravel 5.3 есть команда ремесленников: $ php artisan storage: ссылка
— Фил

22

Согласно документации Laravel 5.2, ваши общедоступные файлы должны быть помещены в каталог

storage/app/public

Чтобы сделать их доступными из Интернета, вы должны создать символическую ссылку с public/storageна storage/app/public.

ln -s /path/to/laravel/storage/app/public /path/to/laravel/public/storage

Теперь вы можете создать в своем представлении URL-адрес для файлов, используя помощник по активам:

echo asset('storage/file.txt');


13

Прежде всего вам нужно создать символическую ссылку для каталога хранилища с помощью команды artisan

php artisan storage:link

Тогда в любом представлении вы можете получить доступ к своему изображению через URL-помощник, как это.

url('storage/avatars/image.png');

4

Хорошо сохранить все личные изображения и документы в директории хранения, тогда у вас будет полный контроль над файловым эфиром, который вы можете разрешить определенному типу пользователей для доступа к файлу или ограничить.

Создайте маршрут / документацию и укажите любой метод контроллера:

public function docs() {

    //custom logic

    //check if user is logged in or user have permission to download this file etc

    return response()->download(
        storage_path('app/users/documents/4YPa0bl0L01ey2jO2CTVzlfuBcrNyHE2TV8xakPk.png'), 
        'filename.png',
        ['Content-Type' => 'image/png']
    );
}

Когда вы нажмете localhost:8000/docsфайл будет загружен, если таковой существует.

Файл должен находиться в root/storage/app/users/documentsкаталоге в соответствии с приведенным выше кодом, это было проверено на Laravel 5.4.


4

Если вы хотите загрузить небольшое количество личных изображений, вы можете кодировать изображения в base64 и выводить их <img src="{{$image_data}}">напрямую:

$path = image.png
$full_path = Storage::path($path);
$base64 = base64_encode(Storage::get($path));
$image_data = 'data:'.mime_content_type($full_path) . ';base64,' . $base64;

Я упомянул приватный, потому что вы должны использовать эти методы только в том случае, если вы не хотите хранить изображения, общедоступные через URL, вместо этого вы должны всегда использовать стандартный способ (связать хранилище / общую папку и обслуживать изображения с HTTP-сервером).

Остерегайтесь кодирования, чтобы base64()иметь две важные недостатки:

  1. Это увеличит размер изображения на ~ 30%.
  2. Вы объединяете все размеры изображений в одном запросе, вместо того, чтобы загружать их параллельно, это не должно быть проблемой для некоторых небольших миниатюр, но для многих изображений избегайте использования этого метода.

2

Если вы используете php, просто воспользуйтесь функцией php symlink, например:

symlink('/home/username/projectname/storage/app/public', '/home/username/public_html/storage')

измените имя пользователя и имя проекта на правильные имена.


1

без названия сайта

{{Storage::url($photoLink)}}

если вы хотите добавить имя сайта к нему, пример добавить в API JSON FELIDS

 public function getPhotoFullLinkAttribute()
{
    return env('APP_URL', false).Storage::url($this->attributes['avatar']) ;
}

0

Если вы похожи на меня и у вас каким-то образом есть полные пути к файлам (я сделал несколько шаблонов glob () на требуемых фотографиях, так что в итоге получаю полные пути к файлам), и ваши настройки хранилища хорошо связаны (то есть такие, что ваши пути есть строка storage/app/public/), тогда вы можете использовать мой маленький грязный хак ниже: р)

 public static function hackoutFileFromStorageFolder($fullfilePath) {
        if (strpos($fullfilePath, 'storage/app/public/')) {
           $fileParts = explode('storage/app/public/', $fullfilePath);
           if( count($fileParts) > 1){
               return $fileParts[1];
           }
        }

        return '';
    }

0

Если у вас не работает локальный диск, попробуйте это:

  1. Изменить местный на общедоступный в 'default' => env('FILESYSTEM_DRIVER', 'public'),сproject_folder/config/filesystem.php
  2. Очистить кеш настроек php artisan config:clear
  3. Затем создайте сим-ссылку php artisan storage:link

Чтобы получить URL загруженного изображения, вы можете использовать это Storage::url('iamge_name.jpg');

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.