Файловое хранилище
11.x
.
Почему это важно?
- Введение
- Конфигурирование
- Локальный драйвер
- Публичный диск
- Предварительная подготовка драйверов
- Файловые системы, совместимые с Amazon S3
- Кеширование
- Доступ к экземплярам дисков
- Диски по запросу
- Получение файлов
- Скачивание файлов
- URL-адреса файлов
- Метаданные файла
- Хранение файлов
- Загрузка файлов
- Видимость файла
- Удаление файлов
- Каталоги
- Пользовательские файловые системы
Введение
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
:
use Illuminate\Support\Facades\Storage;
Storage::disk('local')->put('example.txt', 'Contents');
Публичный диск
Диск public
, определенный в файле конфигурации filesystems
вашего приложения, предназначен для файлов, которые будут общедоступными. По умолчанию публичный диск использует драйвер local
и хранит свои файлы в storage/app/public
.
Чтобы сделать эти файлы доступными из интернета, вы должны создать символическую ссылку на storage/app/public
в public/storage
. Использование этого соглашения о папках позволит хранить ваши публичные файлы в одном каталоге, который может быть легко доступен между развертываниями при использовании систем развертывания с нулевым временем простоя, таких как Envoyer.
Чтобы создать символическую ссылку, вы можете использовать команду storage:link
Artisan:
php artisan storage:link
После того как была создана символическая ссылка, вы можете создавать URL-адреса для сохраненных файлов, используя помощник asset
:
echo asset('storage/file.txt');
Вы можете настроить дополнительные символические ссылки в файле конфигурации filesystems
. Каждая из настроенных ссылок будет создана, когда вы запустите команду storage:link
:
'links' => [
public_path('storage') => storage_path('app/public'),
public_path('images') => storage_path('app/images'),
],
Предварительная подготовка драйверов
Пакеты Composer
Перед использованием драйверов S3 или SFTP вам необходимо установить соответствующий пакет с помощью менеджера пакетов Composer:
- Amazon S3:
composer require --with-all-dependencies league/flysystem-aws-s3-v3 "^1.0"
- SFTP:
composer require league/flysystem-sftp "~1.0"
Кроме того, вы можете установить декоратор CachedAdapter для повышения производительности:
- CachedAdapter:
composer require league/flysystem-cached-adapter "~1.0"
Конфигурирование драйвера S3
Информация о конфигурации драйвера S3 находится в вашем файле конфигурации config/filesystems.php
. Этот файл содержит пример массива конфигурации для драйвера S3. Вы можете изменить этот массив своей собственной конфигурацией S3 и учетными данными. Для удобства эти переменные среды соответствуют соглашению об именах, используемому в интерфейсе командной строки AWS.
Конфигурирование драйвера FTP
Интеграция Laravel с Flysystem отлично работает с FTP; однако, пример конфигурации по умолчанию не включен в конфигурационный файл config/filesystems.php
фреймворка. Если вам нужно настроить файловую систему FTP, вы можете использовать пример конфигурации ниже:
'ftp' => [
'driver' => 'ftp',
'host' => env('FTP_HOST'),
'username' => env('FTP_USERNAME'),
'password' => env('FTP_PASSWORD'),
// Optional FTP Settings...
// 'port' => env('FTP_PORT', 21),
// 'root' => env('FTP_ROOT'),
// 'passive' => true,
// 'ssl' => true,
// 'timeout' => 30,
],
Конфигурирование драйвера SFTP
Интеграция Laravel с Flysystem отлично работает с SFTP; однако, пример конфигурации по умолчанию не включен в конфигурационный файл config/filesystems.php
фреймворка. Если вам нужно настроить файловую систему SFTP, вы можете использовать пример конфигурации ниже:
'sftp' => [
'driver' => 'sftp',
'host' => env('SFTP_HOST'),
// Settings for basic authentication...
'username' => env('SFTP_USERNAME'),
'password' => env('SFTP_PASSWORD'),
// Settings for SSH key based authentication with encryption password...
'privateKey' => env('SFTP_PRIVATE_KEY'),
'password' => env('SFTP_PASSWORD'),
// Optional SFTP Settings...
// 'port' => env('SFTP_PORT', 22),
// 'root' => env('SFTP_ROOT'),
// 'timeout' => 30,
],
Файловые системы, совместимые с Amazon S3
По умолчанию файл конфигурации вашего приложения filesystems
содержит конфигурацию диска для диска s3
. Помимо использования этого диска для взаимодействия с Amazon S3, вы можете использовать его для взаимодействия с любой совместимой с S3 службой хранения файлов, такой как MinIO или DigitalOcean Spaces.
Обычно после обновления учетных данных диска для соответствия учетным данным службы, которую вы планируете использовать, вам нужно только обновить значение параметра конфигурации url
. Значение этой опции обычно определяется через переменную окружения AWS_ENDPOINT
:
'endpoint' => env('AWS_ENDPOINT', 'https://minio:9000'),
Кеширование
Чтобы включить кеширование для конкретного диска, вы можете добавить директиву cache
в параметры конфигурации этого диска. Параметр cache
должен быть массивом параметров кеширования, содержащим имя кеша store
, время expire
в секундах и prefix
кеша:
's3' => [
'driver' => 's3',
// Other Disk Options...
'cache' => [
'store' => 'memcached',
'expire' => 600,
'prefix' => 'cache-prefix',
],
],
Доступ к экземплярам дисков
Фасад Storage
используется для взаимодействия с любым из ваших сконфигурированных дисков. Например, вы можете использовать метод put
фасада, чтобы сохранить аватар на диске по умолчанию. Если вы вызываете методы фасада Storage
без предварительного вызова метода disk
, то метод будет проксирован на диск по умолчанию:
use Illuminate\Support\Facades\Storage;
Storage::put('avatars/1', $content);
Если ваше приложение взаимодействует с несколькими дисками, то вы можете использовать метод disk
фасада Storage
для работы с файлами на указанном диске:
Storage::disk('s3')->put('avatars/1', $content);
Диски по запросу
Иногда вы можете захотеть создать диск во время выполнения, используя заданную конфигурацию, без того, чтобы эта конфигурация фактически присутствовала в файле конфигурации вашего приложения filesystems
. Для этого вы можете передать массив конфигурации методу build
фасада Storage
:
use Illuminate\Support\Facades\Storage;
$disk = Storage::build([
'driver' => 'local',
'root' => '/path/to/root',
]);
$disk->put('image.jpg', $content);
Получение файлов
Метод get
используется для получения содержимого файла. Необработанное строковое содержимое файла будет возвращено методом. Помните, что все пути к файлам должны быть указаны относительно «корня» диска:
$contents = Storage::get('file.jpg');
Метод exists
используется для определения, существует ли файл на диске:
if (Storage::disk('s3')->exists('file.jpg')) {
// ...
}
Метод missing
используется, чтобы определить, отсутствует ли файл на диске:
if (Storage::disk('s3')->missing('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
.
При использовании драйвера
local
возвращаемое значениеurl
не является URL-кодированным. По этой причине мы рекомендуем всегда хранить ваши файлы, используя имена, которые будут создавать допустимые URL-адреса.
Временные URL
Используя метод temporaryUrl
, вы можете создавать временные URL-адреса для файлов, хранящихся с помощью драйвера s3
. Этот метод принимает путь и экземпляр DateTime
, указывающий, когда должен истечь доступ к файлу по URL:
use Illuminate\Support\Facades\Storage;
$url = Storage::temporaryUrl(
'file.jpg', now()->addMinutes(5)
);
Если вам нужно указать дополнительные параметры запроса S3, то вы можете передать массив параметров запроса в качестве третьего аргумент методу temporaryUrl
:
$url = Storage::temporaryUrl(
'file.jpg',
now()->addMinutes(5),
[
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename=file2.jpg',
]
);
Если вам нужно настроить способ создания временных URL-адресов для определенного диска хранилища, вы можете использовать метод buildTemporaryUrlsUsing
. Например, это может быть полезно, если у вас есть контроллер, позволяющий загружать файлы, хранящиеся на диске, который обычно не поддерживает временные URL-адреса. Обычно этот метод следует вызывать из boot
метода сервис-провайдера:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Storage::disk('local')->buildTemporaryUrlsUsing(function ($path, $expiration, $options) {
return URL::temporarySignedRoute(
'files.download',
$expiration,
array_merge($options, ['path' => $path])
);
});
}
}
Настройка хоста URL
Если вы хотите заранее определить хост для URL-адресов, сгенерированных с помощью фасада Storage
, то вы можете добавить параметр 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');
Пути к файлам
Вы можете использовать метод path
, чтобы получить путь к указанному файлу. Если вы используете драйвер local
, он вернет абсолютный путь к файлу. Если вы используете драйвер s3
, этот метод вернет относительный путь к файлу в корзине S3
:
use Illuminate\Support\Facades\Storage;
$path = Storage::path('file.jpg');
Хранение файлов
Метод put
используется для сохранения содержимого файла на диске. Вы также можете передать resource
PHP методу put
, который будет использовать поддержку базового потока Flysystem. Помните, что все пути к файлам должны быть указаны относительно «корневого» расположения, настроенного для диска:
use Illuminate\Support\Facades\Storage;
Storage::put('file.jpg', $contents);
Storage::put('file.jpg', $resource);
Автоматическая потоковая передача
Потоковая передача файлов в хранилище позволяет значительно сократить использование памяти. Если вы хотите, чтобы Laravel автоматически управлял потоковой передачей переданного файла в ваше хранилище, вы можете использовать методы putFile
или putFileAs
. Эти методы принимают экземпляр Illuminate\Http\File
или Illuminate\Http\UploadedFile
и автоматически передают файл в нужное место:
use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;
// Автоматически генерировать уникальный идентификатор для имени файла ...
$path = Storage::putFile('photos', new File('/path/to/photo'));
// Явно указать имя файла ...
$path = Storage::putFileAs('photos', new File('/path/to/photo'), 'photo.jpg');
Следует отметить несколько важных моментов, касающихся метода putFile
. Обратите внимание, что мы указали только имя каталога, а не имя файла. По умолчанию метод putFile
генерирует уникальный идентификатор, который будет служить именем файла. Расширение файла будет определено путем проверки MIME-типа файла. Путь к файлу будет возвращен методом putFile
, так что вы можете сохранить путь, включая сгенерированное имя файла, в вашей базе данных.
Методы putFile
и putFileAs
также принимают аргумент для определения «видимости» сохраненного файла. Это особенно полезно, если вы храните файл на облачном диске, таком как Amazon S3, и хотите, чтобы файл был общедоступным через сгенерированные URL:
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');
Загрузка файлов
В веб-приложениях одним из наиболее распространенных вариантов хранения файлов является хранение загруженных пользователем файлов, таких как фотографии и документы. Laravel упрощает хранение загруженных файлов с помощью метода store
экземпляра загружаемого файла. Вызовите метод store
, указав путь, по которому вы хотите сохранить загруженный файл:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class UserAvatarController extends Controller
{
/**
* Обновить аватар пользователя.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\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
);
Непечатаемые и недопустимые символы Unicode будут автоматически удалены из путей к файлам. По этой причине, вы по желанию можете очистить пути к файлам перед их передачей в методы хранения файлов Laravel. Пути к файлам нормализуются с помощью метода
League\Flysystem\Util::normalizePath
.
Указание диска
По умолчанию метод store
загружаемого файла будет использовать ваш диск по умолчанию. Если вы хотите указать другой диск, передайте имя диска в качестве второго аргумента методу store
:
$path = $request->file('avatar')->store(
'avatars/'.$request->user()->id, 's3'
);
Если вы используете метод storeAs
, вы можете передать имя диска в качестве третьего аргумента метода:
$path = $request->file('avatar')->storeAs(
'avatars',
$request->user()->id,
's3'
);
Другая информация о загружаемом файле
Если вы хотите получить оригинальное имя или расширение загружаемого файла, вы можете сделать это с помощью методов getClientOriginalName
и getClientOriginalExtension
:
$file = $request->file('avatar');
$name = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
Однако имейте в виду, что методы getClientOriginalName
и getClientOriginalExtension
считаются небезопасными, так как имя и расширение файла могут быть изменены злоумышленником. По этой причине вы обычно должны предпочесть методы hashName
и extension
чтобы получить имя и расширение для загружаемого файла:
$file = $request->file('avatar');
$name = $file->hashName(); // Generate a unique, random name...
$extension = $file->extension(); // Determine the file's extension based on the file's MIME type...
Видимость файла
В интеграции Laravel 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');
При взаимодействии с загружаемыми файлами, вы можете использовать методы storePublicly
и storePubliclyAs
для сохранения загружаемого файла с видимостью public
:
$path = $request->file('avatar')->storePublicly('avatars', 's3');
$path = $request->file('avatar')->storePubliclyAs(
'avatars',
$request->user()->id,
's3'
);
Локальные файлы и видимость
При использовании драйвера local
, видимость public
интерпретируется в право доступа 0755
для каталогов и право доступа 0644
для файлов. Вы можете изменить сопоставление прав доступа в файле конфигурации filesystems
вашего приложения:
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'permissions' => [
'file' => [
'public' => 0644,
'private' => 0600,
],
'dir' => [
'public' => 0755,
'private' => 0700,
],
],
],
Удаление файлов
Метод 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('path/file.jpg');
Каталоги
Получение всех файлов каталога
Метод files
возвращает массив всех файлов указанного каталога. Если вы хотите получить список всех файлов каталога, включая все подкаталоги, вы можете использовать метод allFiles
:
use Illuminate\Support\Facades\Storage;
$files = Storage::files($directory);
$files = Storage::allFiles($directory);
Получение всех каталогов из каталога
Метод directories
возвращает массив всех каталогов указанного каталога. Кроме того, вы можете использовать метод allDirectories
, чтобы получить список всех каталогов внутри указанного каталога и всех его подкаталогов:
$directories = Storage::directories($directory);
$directories = Storage::allDirectories($directory);
Создание каталога
Метод makeDirectory
создаст указанный каталог, включая все необходимые подкаталоги:
Storage::makeDirectory($directory);
Удаление каталога
Наконец, для удаления каталога и всех его файлов можно использовать метод deleteDirectory
:
Storage::deleteDirectory($directory);
Пользовательские файловые системы
Интеграция Laravel с Flysystem обеспечивает поддержку нескольких «драйверов» из коробки; однако, Flysystem этим не ограничивается и имеет адаптеры для многих других систем хранения. Вы можете создать собственный драйвер, если хотите использовать один из этих дополнительных адаптеров в своем приложении Laravel.
Чтобы определить собственную файловую систему, вам понадобится адаптер Flysystem. Давайте добавим в наш проект адаптер Dropbox, поддерживаемый сообществом:
composer require spatie/flysystem-dropbox
Затем вы можете зарегистрировать драйвер в методе boot
одного из поставщиков служб вашего приложения. Для этого вы должны использовать метод extend
фасада Storage
:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\ServiceProvider;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;
class AppServiceProvider extends ServiceProvider
{
/**
* Регистрация любых служб приложения.
*
* @return void
*/
public function register()
{
//
}
/**
* Загрузка любых служб приложения.
*
* @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
для указанного диска.
После того как вы создали и зарегистрировали расширение поставщика службы, вы можете использовать драйвер dropbox
в вашем файле конфигурации config/filesystems.php
.