- Введение
- Конфигурирование
- Доступ к экземплярам дисков
- Получение файлов
- Хранение файлов
- Удаление файлов
- Каталоги
- Пользовательские файловые системы
Laravel обеспечивает мощную абстракцию файловой системы благодаря замечательному пакету Flysystem PHP от Фрэнка де Йонга. Интеграция Laravel с Flysystem предоставляет простые драйверы для работы с локальными файловыми системами, SFTP и Amazon S3. Более того, удивительно просто переключаться между этими вариантами хранения: как локального, так и производственного серверов – поскольку API остается одинаковым для каждой системы.
Файл конфигурации файловой системы Laravel находится в config/filesystems.php
. В этом файле вы можете настроить все «диски» файловой системы. Каждый диск представляет собой определенный драйвер хранилища и место хранения. Примеры конфигураций для каждого поддерживаемого драйвера включены в файл конфигурации, так что вы можете изменить конфигурацию, отражающую ваши предпочтения хранения и учетные данные.
Драйвер local
взаимодействует с файлами, хранящимися локально на сервере, на котором запущено приложение Laravel, в то время как драйвер s3
используется для записи в службу облачного хранилища Amazon S3.
{tip} Вы можете настроить столько дисков, сколько захотите, и даже иметь несколько дисков, использующих один и тот же драйвер.
При использовании драйвера 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'),
],
Перед использованием драйверов S3 или SFTP вам необходимо установить соответствующий пакет с помощью менеджера пакетов Composer:
- Amazon S3:
league/flysystem-aws-s3-v3 ~1.0
- SFTP:
league/flysystem-sftp ~1.0
Кроме того, вы можете установить декоратор CachedAdapter для повышения производительности:
- CachedAdapter:
league/flysystem-cached-adapter ~1.0
Информация о конфигурации драйвера S3 находится в вашем файле конфигурации config/filesystems.php
. Этот файл содержит пример массива конфигурации для драйвера S3. Вы можете изменить этот массив своей собственной конфигурацией S3 и учетными данными. Для удобства эти переменные среды соответствуют соглашению об именах, используемому в интерфейсе командной строки AWS.
Интеграция Laravel с 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,
],
Интеграция Laravel с Flysystem отлично работает с 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
в параметры конфигурации этого диска. Параметр cache
должен быть массивом параметров кеширования, содержащим имя disk
, время 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);
Метод 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 для указанного файла. Если вы используете драйвер local
, он обычно просто добавляет /storage
к указанному пути и возвращает относительный URL-адрес файла. Если вы используете драйвер s3
, будет возвращен абсолютный внешний URL-адрес:
use Illuminate\Support\Facades\Storage;
$url = Storage::url('file.jpg');
При использовании драйвера local
все файлы, которые должны быть общедоступными, должны быть помещены в каталог storage/app/public
. Кроме того, вы должны создать символическую ссылку в public/storage
, которая указывает на каталог storage/app/public
.
{note} При использовании драйвера
local
возвращаемое значение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-адресов, сгенерированных с помощью фасада 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
);
{note} Непечатаемые и недопустимые символы 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
:
$name = $request->file('avatar')->getClientOriginalName();
Метод extension
может использоваться для получения расширения загружаемого файла:
$extension = $request->file('avatar')->extension();
В интеграции 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' => 0664,
'private' => 0600,
],
'dir' => [
'public' => 0775,
'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
.