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

Якщо ви використовуєте Бібліотеку зображень інтервенції, ви можете використовувати її вбудований responseметод, щоб зробити речі більш лаконічними:

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

УВАГА

Майте на увазі, що вручну подаючи файли, ви несуть штрафи за ефективність , оскільки ви переживаєте весь життєвий цикл запиту Laravel, щоб прочитати та надіслати вміст файлу, що значно повільніше, ніж обробляти його HTTP-сервером.


Це здається гарним. Я хотів би задати ще одне питання. Чи рекомендується зберігати такі файли, як аватари, великі пальці тощо (завантажені файли від користувачів) у сховищі?
Tadeáš Jílek

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

2
Особисто я не зберігав би файли користувачів у загальнодоступній папці, я вважаю речі набагато акуратнішими та керованішими, коли папка зберігання використовується для зберігання.
SlateEntropy

2
Я б не рекомендував жодне з них, тому що ви знову додаєте накладні витрати на завантаження Laravel та / або використовуєте PHP для читання кожного зображення. Використання символьного посилання, як описано у CmdSft, було б набагато швидше.
user1960364

4
@ user1960364 Ось чому останній абзац настійно пропонує використовувати підхід symlink. Але сама відповідь, хоча і не найкраще рішення з точки зору продуктивності, все-таки справедлива і може бути єдиним підходом для людей, які працюють із програмами на спільних серверах, де налаштування символьних посилань неможливо. У відповіді також показано, як ви можете програмно обслуговувати файли, якщо виникне потреба, можливо, для подання зашифрованих файлів, як задано в цьому запитанні .
Богдан

53

Одним із варіантів було б створення символічного зв’язку між підпапками у вашому каталозі зберігання та загальнодоступним каталогом.

Наприклад

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

Це також метод , який використовується Envoyer , менеджер розгортання , побудованого Taylor Otwell, розробник Laravel.


Я трохи новачок у цьому. Це потрібно запускати на терміналі чи визначати у файлі config десь у 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 ремісничий сховище: посилання
Phil

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

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

0

Якщо ви схожі на мене, і у вас якимось чином є повний шлях до файлу (я зробив деякий глобус () шаблон узгодження на потрібних фотографіях, тому я в значній мірі закінчується повними шляхами до файлів), і налаштування вашої пам’яті добре пов'язане (тобто таке, що ваші шляхи є рядок storage/app/public/), то ви можете використовувати мій маленький брудний злом нижче: p)

 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

Якщо диск "local" не працює для вас, спробуйте це:

  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.