Где хранить файлы laravel

Обновлено: 04.07.2024

Laravel предоставляет мощную абстракцию для работы с файловой системой благодаря php-пакету Flysystem от Франка де Жонге. Настройки файловой системы находятся в файле config/filesystems.php . В нём можно настроить так называемые «диски». Каждый диск представляет собой определенный драйвер и место хранения. В конфигурационном файле имеются примеры для каждого поддерживаемого драйвера.

Функция storage_path() возвращает полный путь к директории storage . Также можно использовать функцию storage_path() для получения полного пути к указанному файлу относительно директории хранилища:

Функция public_path() возвращает полный путь к директории public , которая является корнем веб-сервера, т.е. доступна из веб. Также можно использовать функцию public_path() для получения полного пути к указанному файлу или директории:

Сразу после установки Laravel доступны диски local и public , использующие драйвер local . Для диска local место хранения — директория storage/app , для диска public место хранения — директория storage/app/public . Диск local является диском по умолчанию.

Какие символьные ссылки создавать — задается в файле конфигурации, см. выше. Когда файл сохранён на диске и создана символьная ссылка, можно создать URL к файлу с помощью хелпера asset() или метода url() фасада Storage .

Методы фасада Storage

При использовании драйвера local все файловые операции выполняются относительно директории root , определенной в конфигурационном файле. Для диска local директория root — это storage/app , для диска public директория root — это storage/app/public .

При вызове метода фасада Storage без предварительного вызова метода disk() — вызов будет автоматически передан диску по умолчанию.

Методом get() можно получать содержимое файла. Он возвращает сырую строку содержимого файла.

Методом exists() можно определить существование файла на диске:

Метод url() позволяет получить URL файла. При использовании диска local будет возвращён URL вида /storage/images/image.jpg . При использовании диска public будет возвращён полный URL, домен сайта будет получен из .env -файла в корне проекта, это настройка APP_URL .

Метод size() позволяет получить размер файла в байтах:

Метод copy() копирует файл, метод move() перемещает файл:

Метод prepend() добавляет содержимое в начало файла, метод append() добавляет содержимое в конец файла:

Метод delete() удаляет указанный файл:

Метод files() возвращает массив имен файлов в указанной директории. А метод allFiles() — массив имен файлов в указанной директории и во всех поддиректориях.

Метод directories() возвращает массив имен директорий в указанной директории. А метод allDirectories() — массив имен директорий в указанной директории и во всех поддиректориях.

Метод makeDirectory() создает новую директорию, а метод deleteDirectory() удаляет указанную директорию.

Загрузка файлов

В Laravel очень просто сохранять загружаемые файлы методом store() на экземпляре загружаемого файла:

Мы указываем только директорию avatars , а имя файла будет сформировано автоматически. Метод вернёт путь к файлу, поэтому можно сохранить в БД весь путь, включая сгенерированное имя. Файл будет сохранен на диск по умолчанию, но можно указать диск вторым аргументом метода store() .

Также можно использовать метод putFile() фасада Storage для выполнения аналогичного действия:

Чтобы задать свое имя файла и (опционально) диск для сохранения, можно использовать метод storeAs() :

Также можно использовать метод putFileAs() фасада Storage для выполнения аналогичного действия:

Laravel обеспечивает мощную абстракцию файловой системы благодаря замечательному пакету Flysystem PHP от Фрэнка де Йонга. Интеграция Laravel с Flysystem содержит простые драйверы для работы с локальными файловыми системами, SFTP и Amazon S3. Более того, удивительно просто переключаться между этими вариантами хранения: как локального, так и производственного серверов – поскольку API остается одинаковым для каждой системы.

Конфигурирование

Файл конфигурации файловой системы Laravel находится в config/filesystems.php . В этом файле вы можете настроить все «диски» файловой системы. Каждый диск представляет собой определенный драйвер хранилища и место хранения. Примеры конфигураций для каждого поддерживаемого драйвера включены в конфигурационный файл, так что вы можете изменить конфигурацию, отражающую ваши предпочтения хранения и учетные данные.

Драйвер local взаимодействует с файлами, хранящимися локально на сервере, на котором запущено приложение Laravel, в то время как драйвер s3 используется для записи в службу облачного хранилища Amazon S3.

Вы можете настроить столько дисков, сколько захотите, и даже иметь несколько дисков, использующих один и тот же драйвер.

Локальный драйвер

При использовании драйвера local все операции с файлами выполняются относительно корневого каталога, определенного в файле конфигурации filesystems . По умолчанию это значение задано каталогом storage/app . Следовательно, следующий метод запишет файл в storage/app/example.txt :

Публичный диск

Диск public , определенный в файле конфигурации filesystems вашего приложения, предназначен для файлов, которые будут общедоступными. По умолчанию публичный диск использует драйвер local и хранит свои файлы в storage/app/public .

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

Чтобы создать символическую ссылку, вы можете использовать команду storage:link Artisan:

После того, как была создана символическая ссылка, вы можете создавать URL-адреса для сохраненных файлов, используя помощник asset :

Вы можете настроить дополнительные символические ссылки в файле конфигурации filesystems . Каждая из настроенных ссылок будет создана, когда вы запустите команду storage:link :

Предварительная подготовка драйверов

Пакеты Composer

Перед использованием драйверов S3 или SFTP вам необходимо установить соответствующий пакет с помощью менеджера пакетов Composer:

    Amazon S3: composer require league/flysystem-aws-s3-v3 "

Кроме того, вы можете установить декоратор CachedAdapter для повышения производительности:

    CachedAdapter: composer require league/flysystem-cached-adapter "

Конфигурирование драйвера S3

Информация о конфигурации драйвера S3 находится в вашем файле конфигурации config/filesystems.php . Этот файл содержит пример массива конфигурации для драйвера S3. Вы можете изменить этот массив своей собственной конфигурацией S3 и учетными данными. Для удобства эти переменные среды соответствуют соглашению об именах, используемому в интерфейсе командной строки AWS.

Конфигурирование драйвера FTP

Интеграция Laravel с Flysystem отлично работает с FTP; однако, пример конфигурации по умолчанию не включен в конфигурационный файл config/filesystems.php фреймворка. Если вам нужно настроить файловую систему FTP, вы можете использовать пример конфигурации ниже:

Конфигурирование драйвера SFTP

Интеграция Laravel с Flysystem отлично работает с SFTP; однако, пример конфигурации по умолчанию не включен в конфигурационный файл config/filesystems.php фреймворка. Если вам нужно настроить файловую систему SFTP, вы можете использовать пример конфигурации ниже:

Кеширование

Чтобы включить кеширование для конкретного диска, вы можете добавить директиву cache в параметры конфигурации этого диска. Параметр cache должен быть массивом параметров кеширования, содержащим имя disk , время expire в секундах и prefix кеша:

Доступ к экземплярам дисков

Фасад Storage используется для взаимодействия с любым из ваших сконфигурированных дисков. Например, вы можете использовать метод put фасада, чтобы сохранить аватар на диске по умолчанию. Если вы вызываете методы фасада Storage без предварительного вызова метода disk , то метод будет проксирован на диск по умолчанию:

Если ваше приложение взаимодействует с несколькими дисками, то вы можете использовать метод disk фасада Storage для работы с файлами на указанном диске:

Получение файлов

Метод get используется для получения содержимого файла. Необработанное строковое содержимое файла будет возвращено методом. Помните, что все пути к файлам должны быть указаны относительно «корня» диска:

Метод exists используется для определения, существует ли файл на диске:

Метод missing используется, чтобы определить, отсутствует ли файл на диске:

Скачивание файлов

URL-адреса файлов

Вы можете использовать метод url , чтобы получить URL для указанного файла. Если вы используете драйвер local , он обычно просто добавляет /storage к указанному пути и возвращает относительный URL-адрес файла. Если вы используете драйвер s3 , будет возвращен абсолютный внешний URL-адрес:

При использовании драйвера local все файлы, которые должны быть общедоступными, должны быть помещены в каталог storage/app/public . Кроме того, вы должны создать символическую ссылку в public/storage , которая указывает на каталог storage/app/public .

При использовании драйвера local возвращаемое значение url не является URL-кодированным. По этой причине мы рекомендуем всегда хранить ваши файлы, используя имена, которые будут создавать допустимые URL-адреса.

Временные URL

Используя метод temporaryUrl , вы можете создавать временные URL-адреса для файлов, хранящихся с помощью драйвера s3 . Этот метод принимает путь и экземпляр DateTime , указывающий, когда должен истечь доступ к файлу по URL:

Если вам нужно указать дополнительные параметры запроса S3, то вы можете передать массив параметров запроса в качестве третьего аргумент методу temporaryUrl :

Настройка хоста URL

Если вы хотите заранее определить хост для URL-адресов, сгенерированных с помощью фасада Storage , то вы можете добавить параметр url в массив конфигурации диска:

Метаданные файла

Помимо чтения и записи файлов, Laravel также может предоставлять информацию о самих файлах. Например, метод size используется для получения размера файла в байтах:

Метод lastModified возвращает временную метку UNIX последнего изменения файла:

Пути к файлам

Вы можете использовать метод path , чтобы получить путь к указанному файлу. Если вы используете драйвер local , он вернет абсолютный путь к файлу. Если вы используете драйвер s3 , этот метод вернет относительный путь к файлу в корзине S3 :

Хранение файлов

Метод put используется для сохранения содержимого файла на диске. Вы также можете передать resource PHP методу put , который будет использовать поддержку базового потока Flysystem. Помните, что все пути к файлам должны быть указаны относительно «корневого» расположения, настроенного для диска:

Автоматическая потоковая передача

Следует отметить несколько важных моментов, касающихся метода putFile . Обратите внимание, что мы указали только имя каталога, а не имя файла. По умолчанию метод putFile генерирует уникальный идентификатор, который будет служить именем файла. Расширение файла будет определено путем проверки MIME-типа файла. Путь к файлу будет возвращен методом putFile , так что вы можете сохранить путь, включая сгенерированное имя файла, в вашей базе данных.

Методы putFile и putFileAs также принимают аргумент для определения «видимости» сохраненного файла. Это особенно полезно, если вы храните файл на облачном диске, таком как Amazon S3, и хотите, чтобы файл был общедоступным через сгенерированные URL:

Добавление информации к файлам

Методы prepend и append позволяют записывать в начало или конец файла, соответственно:

Копирование и перемещение файлов

Метод copy используется для копирования существующего файла в новое место на диске, а метод move используется для переименования или перемещения существующего файла в новое место:

Загрузка файлов

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

В этом примере следует отметить несколько важных моментов. Обратите внимание, что мы указали только имя каталога, а не имя файла. По умолчанию метод store генерирует уникальный идентификатор, который будет служить именем файла. Расширение файла будет определено путем проверки MIME-типа файла. Путь к файлу будет возвращен методом store , поэтому вы можете сохранить путь, включая сгенерированное имя файла, в своей базе данных.

Вы также можете вызвать метод putFile фасада Storage , чтобы выполнить ту же операцию сохранения файлов, что и в примере выше:

Указание имени файла

Если вы не хотите, чтобы имя файла автоматически присваивалось вашему сохраненному файлу, вы можете использовать метод storeAs , который получает путь, имя файла и (необязательный) диск в качестве аргументов:

Вы также можете использовать метод putFileAs фасада Storage , который будет выполнять ту же операцию сохранения файлов, что и в примере выше:

Непечатаемые и недопустимые символы Unicode будут автоматически удалены из путей к файлам. По этой причине, вы по желанию можете очистить пути к файлам перед их передачей в методы хранения файлов Laravel. Пути к файлам нормализуются с помощью метода League\Flysystem\Util::normalizePath .

Указание диска

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

Если вы используете метод storeAs , вы можете передать имя диска в качестве третьего аргумента метода:

Другая информация о загружаемом файле

Если вы хотите получить оригинальное имя загружаемого файла, вы можете сделать это с помощью метода getClientOriginalName :

Метод extension используется для получения расширения загружаемого файла:

Видимость файла

В интеграции Laravel Flysystem «видимость» – это абстракция прав доступа к файлам на нескольких платформах. Файлы могут быть объявлены public или private . Когда файл объявляется public , вы указываете, что файл обычно должен быть доступен для других. Например, при использовании драйвера s3 вы можете получить URL-адреса для public файлов.

Вы можете задать видимость при записи файла с помощью метода put :

Если файл уже был сохранен, его видимость может быть получена и задана с помощью методов getVisibility и setVisibility , соответственно:

При взаимодействии с загружаемыми файлами, вы можете использовать методы storePublicly и storePubliclyAs для сохранения загружаемого файла с видимостью public :

Локальные файлы и видимость

При использовании драйвера local , видимость public интерпретируется в право доступа 0755 для каталогов и право доступа 0644 для файлов. Вы можете изменить сопоставление прав доступа в файле конфигурации filesystems вашего приложения:

Удаление файлов

Метод delete принимает имя одного файла или массив имен файлов для удаления:

При необходимости вы можете указать диск, с которого следует удалить файл:

Каталоги

Получение всех файлов каталога

Метод files возвращает массив всех файлов указанного каталога. Если вы хотите получить список всех файлов каталога, включая все подкаталоги, вы можете использовать метод allFiles :

Получение всех каталогов из каталога

Метод directories возвращает массив всех каталогов указанного каталога. Кроме того, вы можете использовать метод allDirectories , чтобы получить список всех каталогов внутри указанного каталога и всех его подкаталогов:

Создание каталога

Метод makeDirectory создаст указанный каталог, включая все необходимые подкаталоги:

Удаление каталога

Наконец, для удаления каталога и всех его файлов можно использовать метод deleteDirectory :

Пользовательские файловые системы

Интеграция Laravel с Flysystem обеспечивает поддержку нескольких «драйверов» из коробки; однако, Flysystem этим не ограничивается и имеет адаптеры для многих других систем хранения. Вы можете создать собственный драйвер, если хотите использовать один из этих дополнительных адаптеров в своем приложении Laravel.

Чтобы определить собственную файловую систему, вам понадобится адаптер Flysystem. Давайте добавим в наш проект адаптер Dropbox, поддерживаемый сообществом:

Затем вы можете зарегистрировать драйвер в методе boot одного из поставщиков служб вашего приложения. Для этого вы должны использовать метод extend фасада Storage :

Laravel обеспечивает мощную абстракцию файловой системы благодаря замечательному PHP-пакету Flysystem Фрэнка де Йонга. Интеграция Laravel Flysystem предоставляет простые в использовании драйверы для работы с локальными файловыми системами, Amazon S3 и Rackspace Cloud Storage. Более того, удивительно просто переключаться между этими вариантами хранения, поскольку API остается одинаковым для каждой системы.

Конфигурация

Файл конфигурации файловой системы находится по адресу . В этом файле вы можете настроить все ваши «диски». Каждый диск представляет определенный драйвер хранилища и место хранения. Примеры конфигурации для каждого поддерживаемого драйвера включены в файл конфигурации. Поэтому измените конфигурацию в соответствии с вашими предпочтениями и учетными данными. config/filesystems.php

Вы можете настроить столько дисков, сколько хотите, и даже иметь несколько дисков, которые используют один и тот же драйвер.

Публичный диск

public Диск предназначен для файлов , которые будут доступны для общественности. По умолчанию public диск использует local драйвер и сохраняет эти файлы в . Чтобы сделать их доступными из Интернета, вы должны создать символическую ссылку с на . Это соглашение будет хранить ваши общедоступные файлы в одном каталоге, который может быть легко распространен между развертываниями при использовании систем развертывания с нулевым временем простоя, таких как Envoyer . storage/app/public public/storage storage/app/public

Чтобы создать символическую ссылку, вы можете использовать команду Artisan: storage:link

После сохранения файла и создания символической ссылки вы можете создать URL-адрес для файлов с помощью asset помощника:

Местный водитель

При использовании local драйвера все файловые операции относятся к root каталогу, определенному в вашем файле конфигурации. По умолчанию это значение установлено в каталог. Поэтому следующий метод будет хранить файл в : storage/app storage/app/file.txt

Необходимые условия для водителя

Композитор Пакеты

Перед использованием драйверов SFTP, S3 или Rackspace вам необходимо установить соответствующий пакет через Composer:

Для производительности абсолютно необходимо использовать кэшированный адаптер. Для этого вам понадобится дополнительный пакет:

Конфигурация драйвера S3

Информация о конфигурации драйвера S3 находится в вашем файле конфигурации. Этот файл содержит пример массива конфигурации для драйвера S3. Вы можете изменить этот массив с помощью своей собственной конфигурации и учетных данных S3. Для удобства эти переменные среды соответствуют соглашению об именах, используемому AWS CLI. config/filesystems.php

Конфигурация драйвера FTP

Интеграция Laravel с Flysystem прекрасно работает с FTP; однако пример конфигурации не включен в файл конфигурации фреймворка по умолчанию . Если вам нужно настроить файловую систему FTP, вы можете использовать пример конфигурации ниже: filesystems.php

Конфигурация драйвера SFTP

Интеграция Laravel с Flysystem прекрасно работает с SFTP; однако пример конфигурации не включен в файл конфигурации фреймворка по умолчанию . Если вам нужно настроить файловую систему SFTP, вы можете использовать пример конфигурации ниже: filesystems.php

Конфигурация Rackspace Driver

Интеграция Laravel с Flysystem прекрасно работает с Rackspace; однако пример конфигурации не включен в файл конфигурации фреймворка по умолчанию . Если вам нужно настроить файловую систему Rackspace, вы можете использовать пример конфигурации ниже: filesystems.php

Кэширование

Чтобы включить кэширование для данного диска, вы можете добавить cache директиву к параметрам конфигурации диска. Параметр cache должен быть массивом параметров кэширования, содержащих disk имя, expire время в секундах и кэш prefix :

Получение экземпляров диска

Storage Фасад может быть использован для взаимодействия с любым из ваших настроенных дисков. Например, вы можете использовать put метод на фасаде, чтобы сохранить аватар на диске по умолчанию. Если вы вызываете методы на Storage фасаде без предварительного вызова disk метода, вызов метода будет автоматически передан на диск по умолчанию:

Если ваше приложение взаимодействует с несколькими дисками, вы можете использовать disk метод на Storage фасаде для работы с файлами на определенном диске:

Получение файлов

Этот get метод может использоваться для извлечения содержимого файла. Необработанное содержимое строки файла будет возвращено методом. Помните, что все пути к файлам должны быть указаны относительно «корневого» расположения, настроенного для диска:

Этот exists метод может использоваться для определения того, существует ли файл на диске:

Загрузка файлов

URL файлов

Вы можете использовать url метод, чтобы получить URL для данного файла. Если вы используете local драйвер, он обычно просто добавляется /storage к указанному пути и возвращает относительный URL-адрес файла. Если вы используете драйвер s3 или rackspace , полный URL-адрес удаленного будет возвращен:

Помните, что если вы используете local драйвер, все файлы, которые должны быть общедоступными, должны быть помещены в каталог. Кроме того, вы должны создать символическую ссылку, по которой указывается каталог. storage/app/public public/storage storage/app/public

Временные URL

Для файлов, хранящихся с использованием драйвера s3 или rackspace , вы можете создать временный URL-адрес для данного файла, используя temporaryUrl метод. Этот метод принимает путь и DateTime экземпляр, указывающий, когда должен истечь URL:

Если вам нужно указать дополнительные параметры запроса S3 , вы можете передать массив параметров запроса в качестве третьего аргумента temporaryUrl методу:

Настройка хоста локального URL

Если вы хотите предварительно определить хост для файлов, хранящихся на диске, с помощью local драйвера, вы можете добавить url опцию в массив конфигурации диска:

Метаданные файла

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

lastModified Метод возвращает UNIX метку последнего времени файл был изменен:

Хранение файлов

Этот put метод может использоваться для хранения необработанного содержимого файла на диске. Вы также можете передать PHP resource в put метод, который будет использовать базовую потоковую поддержку Flysystem. Использование потоков очень рекомендуется при работе с большими файлами:

Автоматическая трансляция

Есть несколько важных вещей, которые стоит отметить в отношении putFile метода. Обратите внимание, что мы указали только имя каталога, а не имя файла. По умолчанию putFile метод генерирует уникальный идентификатор в качестве имени файла. Расширение файла будет определено путем изучения типа файла MIME. Путь к файлу будет возвращен putFile методом, чтобы вы могли сохранить путь, включая сгенерированное имя файла, в вашей базе данных.

В putFile и putFileAs методы также принимают аргумент , чтобы указать «видимость» сохраненный файл. Это особенно полезно, если вы храните файл на облачном диске, таком как S3, и хотите, чтобы файл был общедоступным:

Добавление и добавление в файлы

В prepend и append методы позволяют писать в начало или конец файла:

Копирование и перемещение файлов

Этот copy метод может использоваться для копирования существующего файла в новое место на диске, в то время как move метод может использоваться для переименования или перемещения существующего файла в новое место:

Загрузка файлов

В веб-приложениях одним из наиболее распространенных сценариев использования для хранения файлов является хранение загруженных пользователем файлов, таких как изображения профиля, фотографии и документы. Laravel позволяет очень легко хранить загруженные файлы, используя store метод для экземпляра загруженного файла. Вызовите store метод с путем, по которому вы хотите сохранить загруженный файл:

В этом примере следует отметить несколько важных моментов. Обратите внимание, что мы указали только имя каталога, а не имя файла. По умолчанию store метод генерирует уникальный идентификатор в качестве имени файла. Расширение файла будет определено путем изучения типа файла MIME. Путь к файлу будет возвращен store методом, чтобы вы могли сохранить путь, включая сгенерированное имя файла, в вашей базе данных.

Вы также можете вызвать putFile метод на Storage фасаде, чтобы выполнить те же манипуляции с файлами, что и в примере выше:

Указание имени файла

Если вы не хотите, чтобы имя файла автоматически присваивалось вашему сохраненному файлу, вы можете использовать storeAs метод, который получает путь, имя файла и (необязательно) диск в качестве аргументов:

Вы также можете использовать putFileAs метод на Storage фасаде, который будет выполнять те же операции с файлами, что и в примере выше:

Указание диска

По умолчанию этот метод будет использовать ваш диск по умолчанию. Если вы хотите указать другой диск, передайте имя диска в качестве второго аргумента store методу:

Видимость файла

В интеграции Flysystem от Laravel «видимость» - это абстракция прав доступа к файлам на разных платформах. Файлы могут быть либо объявлены, public либо private . Когда файл объявляется public , вы указываете, что файл, как правило, должен быть доступен для других. Например, при использовании драйвера S3 вы можете получить URL-адреса для public файлов.

Вы можете установить видимость при настройке файла с помощью put метода:

Если файл уже был сохранен, его видимость может быть получена и установить с помощью getVisibility и setVisibility методов:

Удаление файлов

delete Метод принимает один имя файла или массив файлов для удаления с диска:

При необходимости вы можете указать диск, с которого следует удалить файл:

Справочники

Получить все файлы в каталоге

files Метод возвращает массив всех файлов в заданном каталоге. Если вы хотите получить список всех файлов в данном каталоге, включая все подкаталоги, вы можете использовать allFiles метод:

Получить все каталоги в каталоге

directories Метод возвращает массив всех каталогов в данном каталоге. Кроме того, вы можете использовать allDirectories метод для получения списка всех каталогов в данном каталоге и всех его подкаталогах:

Создать каталог

makeDirectory Метод создания данного каталога, включая все необходимые подкаталоги:

Удалить каталог

Наконец, deleteDirectory метод может быть использован для удаления каталога и всех его файлов:

Пользовательские файловые системы

Интеграция Laravel с Flysystem предоставляет драйверы для нескольких «драйверов» из коробки; однако Flysystem этим не ограничивается и имеет адаптеры для многих других систем хранения. Вы можете создать собственный драйвер, если хотите использовать один из этих дополнительных адаптеров в приложении Laravel.

Для настройки пользовательской файловой системы вам понадобится адаптер Flysystem. Давайте добавим в наш проект поддерживаемый сообществом адаптер Dropbox:

Затем вы должны создать поставщика услуг, такого как DropboxServiceProvider . В boot методе провайдера вы можете использовать метод Storage фасада extend для определения пользовательского драйвера:

Время от времени бывает необходимо организовать файловое хранилище за пределами /public. Например, для того, чтобы контролировать доступ к файлам (недоступным по прямой ссылке) по неким правилам.

Сходу из коробки в Laravel 6 такая фича на 100% не предусмотрена, но сделать её руками достаточно нетрудно.

Для начала разобьем задачу на части. Нам нужно:

  1. Определить, где будут храниться файлы (private storage).
  2. Прикреплять файлы к некой модели, чтобы на основе этой модели управлять доступом.
  3. Обеспечить сохранение файлов в private storage.
  4. Реализовать, собственно, контроль доступа и выдачу файлов по некоему пути.
  5. На закуску добавим автоматическую генерацию миниатюр.

1. Private storage

Эта часть как раз реализуется из коробки. Нужно просто пройти в config/fylesystems.php и добавить новый приватный диск, который мы так и назовём — private :

Поскольку вновь созданный диск находится за пределами и не зеркалится в public/ , задача создания приватного пространства уже выполнена. Теперь мы можем обращаться к этому диску из фасада Storage :

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

2. Прикрепляем файлы к модели

Для определенности дальше будем считать, что мы хотим решить задачу: сохранять фотографии сотрудников и сервить их из приватного хранилища. Чтобы те, кто не имеет доступа к условной организации, не могли фотографии сотрудников по прямым ссылкам видеть, а те кто имеет — могли.

Пускай сотрудники описываются моделью Employee . Очевидно, нам нужно связать сохраненные файлы с моделями соответствующих сотрудников. Чтобы не реализовывать хранение-перемещение-рилейшны с файлами на модели самим, воспользуемся одной из библиотек для работы с загрузками и менджментом файлов в Laravel.

Три самых популярных известных мне пакета, позволяющих аттачить файлы к моделям, это:

Воспользуемся первым пакетом, laravel-medialibrary .

Я особо не сравнивал их между собой по фичам. Просто часто пользуюсь пакетами spatie, да и звездочек у них больше :)

Установить пакет можно, как обычно, композером. А для использования достаточно в нужной модели (Employee) реализовать интерфейс HasMedia и добавить трейт HasMediaTrait :

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

3. Сохраняем загруженные файлы

Чтобы библиотека узнала, что файлы требуется сохранять именно в наше приватное хранилище, надо пройти в конфиг config/medialibrary.php и там указать:

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

То есть вызвать $employee->addMedia($file)->toMediaCollection() это всё, что нужно сделать. А остальное (переместить файл на приватный диск, создать модель Media и релейшн) — сделает пакет автоматически.

Стоит отметить, что в методе toMediaCollection() можно указывать коллекцию. То есть коллекций файлов может быть много, и у каждой могут быть какие-то свои настройки.

4. Выдача файлов из хранилища

Теперь нам нужно как-то отдать сохраненный файл пользователю по запросу. Для этого конечно нужен какой-нибудь Url, по которому контроллер сможет определить, что требуется именно этот файл. Добавим новый путь и укажем контроллер и метод-обработчик. Поскольку мы возвращаем картинки сотрудников, укажем это явно в пути, чтобы контроллер понимал, к какой модели Employee относится данный файл.

Здесь у нас — это модель сотрудника, от которого файл, а — некое имя файла, из которого мы должны понять, о каком именно медиа-объекте идет речь. В качестве такого имени хорошо годится id модели Media . По id мы легко найдем модель и возвратим связанный с ней файл.

Теперь создадим контроллер и обработаем запрос пользователя:

Здесь мы сразу получаем модель Employee из запроса, чтобы не описывать отдельно её проверку на существование.

Затем получаем модель авторизованного юзера и проверяем некое правило доступа (например, что Employee принадлежит данному пользователю). И если правило доступа выполняется, возвращаем, собственно, файл. Чтобы получить файл — достаем id модели Media из имени файла.

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

А как получить такой url?

Теперь клиентский браузер, запросив картинку с описанным выше url-ом, сможет её получить. Но тут же встает вопрос — а откуда этот url возьмётся, как он попадет в браузер? Очевидно, надо этот Url каким-то образом сгенерировать. В laravel-medialibrary это делается так:

где $model->getMedia() возвращает коллекцию всех прикрепленных медиа-объектов.

Однако если мы выполним такой код, то немедленно получим исключение. Потому что библиотека laravel-medialibrary не знает, как сгенерировать доступный пользователю url к приватному файлохранилищу. Мы же выше придумали собственное правило генерации пути к таким файлам, соответственно, теперь надо о нём рассказать библиотеке.

Чтобы выдача урла заработала, напишем свой собственный UrlGenerator . В документации на библиотеку об этом написано довольно мало, но ясно главное — нам нужно реализовать метод getUrl() , который сгенерирует нужный нам урл к картинке. А также метод getPath() , возвращающий путь к файлу на диске (нужен Ларавелу чтобы отдать файл клиенту):

Генератор нужно зарегистрировать в конфиге библиотеки:

Теперь мы можем возвращать url-ы для загрузки картинок клиенту, вызывая getUrl() из контроллера, или же переопределив метод toArray() на модели.

Вот так например мы можем вручную сгенерировать и вернуть в JSON массив путей к картинкам, приаттаченным к одной модели $employee .

Заметьте, что генератор в методе getUrl() обращается к медиаобъектам и их родителям. Поэтому чтобы избежать проблемы N+1 запроса, не забудьте про eager loading, прогрузите отношения заранее, до циклических вызовов генерации url:

5. Генерация миниатюр

Также библиотека laravel-medialibrary умеет сама генерировать загруженным картинкам миниатюры (и другие разнообразные преобразования тоже умеет). Для этого нужно только зарегистрировать преобразование на модели:

И миниатюра thumb будет автоматически сгенерирована при сохранении оригинального изображения (также есть возможность подвешивать генерацию на очередь задач).

Чтобы сгенерировать url для миниатюры, нужно в метод getUrl() передать название преобразования:

Но чтобы наш генератор url-ов мог отличить миниатюру от оригинального изображения, нужно его немного доработать:

Таким образом мы закодируем имя преобразования в имени файла, так что для жипега с id модели Media равном 1, имя файла получится 1.thumb.jpg .

На этом всё. Мы сделали приватное файловое хранилище, научились возвращать из него картинки с примитивным контролем доступа, научились сохранять и возвращать миниатюры для этих картинок.

Читайте также: