Хранилище файлов
Содержание:
Введение
Ларавел обеспечивает мощную файловую систему благодаря компоненту PHP
Flysystem от Frank de Jonge.
Интеграция компонента и Ларавел обеспечивает простой для использования драйвер для работы
с локальной файловой системой и Amazon S3. Даже больше это невероятно просто переключаться
между этими опциями хранения, так как API остаётся неизменным для каждой системы.
Конфигурация
Конфигурация файловой системы расположена в config/filesystems.php
. Внутри файла вы
можете настроить в ваши "диски". Каждый дист представляет драйвер и место для хранения. Пример
конфигурации для каждого поддерживаемого диска включён в файл конфигруации. Поэтому измените
конфигруацию, чтобы она отражала ваши предпочтения касательно хранилища данных.
Вы можете настроить так много дисков, как это необходимо вам. Вы даже можете иметь несколько дисков,
которые используют один и тот же драйвер.
Публичный диск
public
диск предназначается для файлов, которые предназначены для публичного доступа.
По умолчанию, диск public
использует драйвер local
и хранит эти файлы
в директории storage/app/public
. Чтобы их сделать доступными, необходимо создать
символическую ссылку из public/storage
в storage/app/public
.
Это сохранит публично-доступные файлы в одной директории, которую можно легко разделить между
точками разработки при использовании систем нулового простая, таких как Envoyer.
Чтобы создать символическую ссылку, вы можете использовать команду Artisan
storage:link
:
php artisan storage:link
После размещения и сохранения файла в директории и создания символической ссылки, вы можете создать URL,
используя команду asset
:
echo asset('storage/file.txt');
Локальный драйвер
При использовании драйвера local
, все операции с файлами привязаны
к директории root
определённой в вашем файле конфигурации filesystems
.
По умолчанию, это значение установлено в директории storage/app
. Таким образом,
следующий метод должен сохранить файл в storage/app/file.txt
:
Storage::disk('local')->put('file.txt', 'Contents');
Разрешения
Установлены разрешения 0755
для публичных папок и 0644
для файлов. Вы можете
изменить разрешения в вашем файле конфигурации filesystems
:
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'permissions' => [
'file' => [
'public' => 0664,
'private' => 0600,
],
'dir' => [
'public' => 0775,
'private' => 0700,
],
],
],
Требования к драйверу
Компоненты Composer
Перед использованием SFTP или S3 драйверов вам необходимо установить соответсвующие компоненты
через Composer:
- SFTP:
league/flysystem-sftp ~1.0
- Amazon S3:
league/flysystem-aws-s3-v3 ~1.0
Для повышения производительности, просто обязательно работать с кэшем.
Для этого нужно установить соответсвующий адаптер:
- CachedAdapter:
league/flysystem-cached-adapter ~1.0
Конфигурация драйвера S3
Информация конфигурации драйвера S3 находится в файле конфигурации config/filesystems.php
.
Это файл содержит пример массива конфигурации для драйвера S3. Вы можете свободно модифицировать
этот массив под ваши нужды. Для удобства переменные окружения соответсвуют названию переменных
используемых AWS CLI.
Конфигурация драйвера FTP
Flysystem Ларавел может отлично работать с FTP; Однако, конфигурация по умолчанию не включена
в базовую сборку фреймворка и конкретно в файл filesystems.php
. Если вам необходимо
настроить систему для работы с FTP, вы можете использовать пример конфигурации:
'ftp' => [
'driver' => 'ftp',
'host' => 'ftp.example.com',
'username' => 'your-username',
'password' => 'your-password',
// Optional FTP Settings...
// 'port' => 21,
// 'root' => '',
// 'passive' => true,
// 'ssl' => true,
// 'timeout' => 30,
],
Конфигурация драйвера SFTP
Как и в случае с FTP, конфигурации SFTP нет в файле filesystems.php
. Ниже представлен
пример конфигурации для настройки SFTP:
'sftp' => [
'driver' => 'sftp',
'host' => 'example.com',
'username' => 'your-username',
'password' => 'your-password',
// Settings for SSH key based authentication...
// 'privateKey' => '/path/to/privateKey',
// 'password' => 'encryption-password',
// Optional SFTP Settings...
// 'port' => 22,
// 'root' => '',
// 'timeout' => 30,
],
Кэширование
Чтобы включить кэширование для данного диска, вы можете добавить опцию cache
в конфигурацию диска. Эта опция должна быть массивом, содержащим следующие параметры:
имя disk
, время в секундах expire
и префикс prefix
:
's3' => [
'driver' => 's3',
// Other Disk Options...
'cache' => [
'store' => 'memcached',
'expire' => 600,
'prefix' => 'cache-prefix',
],
],
Получения экземпляра диска
Фасад Storage
можно использовать для взаимодействия с любым из настроенных дисков.
Например, вы можете ипользовать метод put
для фасада, чтобы сохранить аватар
на диск, указанный по умолчанию:
use Illuminate\Support\Facades\Storage;
Storage::put('avatars/1', $fileContents);
Если ваше приложение взаимодействует с несколькими дисками, вы можете использовать метод
disk
для фасада Storage
, чтобы работать с файлами конкретного диска:
Storage::disk('s3')->put('avatars/1', $fileContents);
Извлечение файлов
Метод get
может быть использован для получения контента файла.
Вернётся содержание файла в виде строки. Также стоит отметить, что все пути файла
должны быть указаны относительно кореневой директории настроенной для диска:
$contents = Storage::get('file.jpg');
Метод exists
может быть использован для определения того, что файл
есть на диске:
$exists = Storage::disk('s3')->exists('file.jpg');
Загрузка файлов
Метод download
может быть использован для того, чтобы сгенерировать ответ,
который заставит браузер пользователь загрузать файл по данному пути. Метод download
принимает имя файла в качестве второго аргумента, который определяет название файла,
которое будет показано пользователю при загрузке. Наконец, вы можете передать массив заголовков HTTP
в качестве третьего аргумента в метод:
return Storage::download('file.jpg');
return Storage::download('file.jpg', $name, $headers);
Файловые URL
Вы можете использовать метод url
, чтобы получить URL для данного файла. Если вы используете
драйвер local
, тогда он просто доставить /storage
в выбранный путь и вернут
относительный URL для файла. Если вы используете драйвер s3
, вернётся полный удалённый URL:
use Illuminate\Support\Facades\Storage;
$url = Storage::url('file.jpg');
Запомните, если вы используете драйвер
local
, все файлы, которые быть публично доступны
должны быть размещены в папке
storage/app/public
. Даже более того, вам стоит создать
символическу ссылку в
public/storage
, которая приведёт
в папку
storage/app/public
.
Временные URLs
При использовании файлов s3
вы можете использовать временный URL для данного файла
используя метод temporaryUrl
. Эти методы принимают путь и экземпляр DateTime
,
уточняющий когда URL должен исчезнуть:
$url = Storage::temporaryUrl(
'file.jpg', now()->addMinutes(5)
);
Если вам необходимо указать дополнительные
параметры запроса S3,
вы можете передать массив параметров запроса в качестве третьего аргумента в метод temporaryUrl
:
$url = Storage::temporaryUrl(
'file.jpg',
now()->addMinutes(5),
['ResponseContentType' => 'application/octet-stream']
);
Настройка локального URL хоста
Если вы хотите предопределить хост для файлов хранящихся на диске с использованием драйвера
local
, вы можете добавить опцию url
в массив конфигурации диска:
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
Дополнительно к чтению и записи файлов, Laravel также может предоставить информацию о файлах.
Например, метод size
может быть использован для получения размера файла в байтах:
use Illuminate\Support\Facades\Storage;
$size = Storage::size('file.jpg');
Метод lastModified
возвращает дату последнего изменения в формате UNIX:
$time = Storage::lastModified('file.jpg');
Хранение файлов
Метод put
может быть использована для того, чтобы сохранить контент файла на диске.
Вы также можете передать PHP resource
в метод put
, который будет использовать
базовую поддержку стрима Flysystem. При работе с большими файлами, настоятельно рекомендуется
настроить работу именно с использованием стримов:
use Illuminate\Support\Facades\Storage;
Storage::put('file.jpg', $contents);
Storage::put('file.jpg', $resource);
Автоматическая потоковая передача
Если вы хотите чтобы Ларавел автоматически настроил управление потоковой передачей данного файла
к вашему месту хранения, вы можете использовать метод putFile
или putFileAs
.
Этот метод принимает как экземпляры Illuminate\Http\File
так и Illuminate\Http\UploadedFile
и автоматически начнёт стрим файла в нужную локацию:
use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;
// Automatically generate a unique ID for file name...
Storage::putFile('photos', new File('/path/to/photo'));
// Manually specify a file name...
Storage::putFileAs('photos', new File('/path/to/photo'), 'photo.jpg');
Есть несколько важных вещей о методе putFile
. Надо заметить, что мы только уточнили
название папки, а не имя файла. По умолчанию, метод putFile
сгенерирует уникальный
идентификатор, в качестве имени файла. Расширение файла будет определено путём проверки MIME типа
файла. Метод putFile
вернёт путь к файлу. Поэтому, вы можете сохранить путь,
включая сгенерированное имя файла в вашу базу данных.
Методы putFile
и putFileAs
также принимают аргумент для указания
видимости сохранённого файла. Это особенно полезно если вы храните файл на облачных дисках,
таких как S3, а файл публично доступен:
Storage::putFile('photos', new File('/path/to/photo'), 'public');
Дописывание в файлы
Методы prepend
и append
позволяют вам дописать
в начало или конец файла:
Storage::prepend('file.log', 'Prepended Text');
Storage::append('file.log', 'Appended Text');
Копирование и перемещение файлов
Метод copy
можно использования для копирования существующих файлов в новую локация
на диске. Метод move
можно использовать для переименования или перемещения существующего
файла в новую директорию:
Storage::copy('old/file.jpg', 'new/file.jpg');
Storage::move('old/file.jpg', 'new/file.jpg');
Загрузка файлов
В веб-приложения, один из наиболее распространённых случаем для хранения файлов это хранение
загреженных файлов пользователя таких как картинки, фото и документы. Ларавел делает очень легким
сохранение файлов используя метод store
для экземпляра загруженного файла.
Вызовите метод store
с путём в который вы хотите, чтобы файл был сохранён:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class UserAvatarController extends Controller
{
/**
* Update the avatar for the user.
*
* @param Request $request
* @return Response
*/
public function update(Request $request)
{
$path = $request->file('avatar')->store('avatars');
return $path;
}
}
Есть несколько важных моментов, которые необходимо значть об этом примере. Заметьте, что мы можем
только указать название папки, а не имя файла. По умолчанию, метод store
сгенерирует
уникальный идентификатор в качестве имени файла. Расширение файла будет определено автоматически
на основе MIME типа. Путь к файлу будет возвращен методом store
, включая имя файла,
поэтому можно сохранить путь, например в базу данных.
Вы можете также вызвать метод putFile
для фасада Storage
, чтобы выполнить
такие же действия как и в примере выше:
$path = Storage::putFile('avatars', $request->file('avatar'));
Указание имение файла
Если вы не хотите, чтобы имя файла было автоматически присвоено загружаемому файлу. вы можете
использовать метод storeAs
, который получает путь, имя файла и (опционально) диск
в качестве аргументов:
$path = $request->file('avatar')->storeAs(
'avatars', $request->user()->id
);
Вы можете также использовать метод putFileAs
для фасада Storage
,
который выполнит такие же операции, как и примере выше:
$path = Storage::putFileAs(
'avatars', $request->file('avatar'), $request->user()->id
);
Непечатные и неверные символы будут автоматически убраны из пути файла. Поэтому вы можете захотеть
очистить путь файла до момента передачи в методы сохранения. Нормализация пути файла можно
провести используя метод League\Flysystem\Util::normalizePath
.
Указание диска
По умолчанию, этот мето будет использовать базовый диск. Если вы хотите указать другой диск,
передайте имя диска в качестве второго параметра в метод store
:
$path = $request->file('avatar')->store(
'avatars/'.$request->user()->id, 's3'
);
Видимость файлов
В Ларавел в контексте компонента Flysystem, видимость — права и разрешения файла
для различных платформ. Файлы могут быть быть задекларированны как
public
или private
. Когда файл задекларированн как public
,
вы показываете что файл должен быть доступен для других. Еще, например, при использовании драйвера S3,
вы можете получить URL для всех файлов public
.
Вы можете установить видимость файла при сохранении для метода put
:
use Illuminate\Support\Facades\Storage;
Storage::put('file.jpg', $contents, 'public');
А если файл уже сохранён, вы можете узнать их видимость или установить через методы
getVisibility
и setVisibility
:
$visibility = Storage::getVisibility('file.jpg');
Storage::setVisibility('file.jpg', 'public')
Удаление файлов
Метод delete
принимает имя файла или массив файлов, которые необходимо удалить из диска:
use Illuminate\Support\Facades\Storage;
Storage::delete('file.jpg');
Storage::delete(['file.jpg', 'file2.jpg']);
При необходимости, можно указать диск, с которого необходимо проводить удаление:
use Illuminate\Support\Facades\Storage;
Storage::disk('s3')->delete('folder_path/file_name.jpg');
Папки
Получение всех файлов внутри директории
Метод files
возвращает массив файлов, которые находятся в данной директории.
Если вы хотите получить все файлы как самой директории, так и вложенных папках, вы можете
использовать метод allFiles
:
use Illuminate\Support\Facades\Storage;
$files = Storage::files($directory);
$files = Storage::allFiles($directory);
Получить все папки внутри директории
Метод directories
возвращает массив всех директрий внутри данной директории.
Дополнитлеьно, вы можете использовать метод allDirectories
для получения
списка папок внутри директории включая те, которые находятся во вложенных папках:
$directories = Storage::directories($directory);
// Recursive...
$directories = Storage::allDirectories($directory);
Создание директрии
Метод makeDirectory
создаст указанную директорнию, включая необходимоые вложенные директории:
Storage::makeDirectory($directory);
Удаление директории
Наконец, метод deleteDirectory
удалит папку и все файлы внутри:
Storage::deleteDirectory($directory);
Пользовательская файловая система
Интеграция компонента Flysystem и Ларавел предусматривает несколько драйверов из коробки.
Нужно понимать, что Flysystem не ограничивается этими решения и существуют и другие адаптеры
для других систем. Вы можете создать пользовательский драйвер, если вы хотите использовать
один из дополнительных адаптеров в вашем приложении.
Чтобы начать рабтать с пользовательской файловой системой вам будет необходимо адаптер Flysystem.
Давайте добавим поддерживаемый сообществом адаптер Dropbox для нашего проекта:
composer require spatie/flysystem-dropbox
После чего, вам следует создать сервис провайдер, такой как DropboxServiceProvider
.
В методе провайдера boot
вы можете использовать метод extend
для
фасада Storage
для определения пользовательского драйвера:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;
use Storage;
class DropboxServiceProvider extends ServiceProvider
{
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Storage::extend('dropbox', function ($app, $config) {
$client = new DropboxClient(
$config['authorization_token']
);
return new Filesystem(new DropboxAdapter($client));
});
}
}
Первый аргумент метода extend
это название драйвер и второй аргумент это замыкание,
кототрое получает переменные $app
и $config
. Должен вернуться экземпляр
League\Flysystem\Filesystem
. Переменная $config
содержит значения,
определённые в config/filesystems.php
для указанного диска.
Следующим шагом необходимо добавить сервис провайдер в файл конфигурации config/app.php
:
'providers' => [
// ...
App\Providers\DropboxServiceProvider::class,
];
После того как вы создали и зарегистрировали сервис провайдер, вы можете использовать
драйвер dropbox
в вашем файле конфигурации config/filesystems.php
.