Laravel (5.7) Файловое хранилище
Загрузка файлов является одной из наиболее часто используемых функций в Интернете. От загрузки аватаров до семейных фотографий и отправки документов по электронной почте мы не можем обойтись без файлов в Интернете. Обработка файлов - это еще одна вещь, которую Laravel упростила в своей экосистеме. Прежде чем мы начнем, нам нужно несколько вещей. Сначала давайте создадим проект Laravel.
composer create-project --prefer-dist laravel/laravel files
Где файлы - это название нашего проекта. После установки приложения нам понадобится установить несколько пакетов, так что давайте их уберем. Обратите внимание, что эти пакеты необходимы только в том случае, если вы собираетесь сохранять изображения в Amazon s3 или манипулировать изображениями, такими как кадрирование, фильтры и т. Д.
composer require league/flysystem-aws-s3-v3:~1.0 intervention/image:~2.4
После установки зависимостей, последняя - Mailtrap. Mailtrap - это фальшивый SMTP-сервер для групп разработчиков, позволяющий тестировать, просматривать и обмениваться сообщениями электронной почты, отправленными из сред разработки и промежуточной среды, без спама от реальных клиентов. Так что зайдите в Mailtrap и создайте новый почтовый ящик для тестирования.
Затем в welcome.blade.php обновите тег head:
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>File uploads</title>
<style>
* {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol";
}
</style>
Modify the body contents to:
<form action="/process" enctype="multipart/form-data" method="POST">
<p>
<label for="photo">
<input type="file" name="photo" id="photo">
</label>
</p>
<button>Upload</button>
{{ csrf_field() }}
</form>
Для формы загрузки файла чрезвычайно важны enctype = "multipart / form-data" и method = "POST", так как браузер знает, как правильно отформатировать запрос. {{csrf_field ()}} специфичен для Laravel и создаст скрытое поле ввода с токеном, который Laravel может использовать для проверки правильности отправки формы.
Если токен CSRF не существует на странице, Laravel покажет страницу «Срок действия страницы истек из-за неактивности».
Теперь, когда у нас есть свои зависимости, давайте начнем.
Понимание того, как Laravel обрабатывает файлы
Развитие в том виде, в каком мы его знаем в 2018 году, быстро растет, и в большинстве случаев существует множество решений одной проблемы. Возьмем, к примеру, файловый хостинг, теперь у нас так много вариантов хранения файлов, огромное количество решений, от самостоятельного размещения до FTP, от облачного хранилища до GFS и многих других.
Поскольку Laravel - это фреймворк, который поощряет гибкость, он имеет собственный способ обработки множества файловых структур. Будь то локальный, Amazon s3, Google Cloud, Laravel вас покроет.
Решение этой проблемы Laravel - называть их дисками. Имеет смысл, любая система хранения файлов, о которой вы только можете подумать, может быть помечена как диск в Laravel. В связи с этим Laravel поставляется с собственной поддержкой некоторых провайдеров (дисков). У нас есть:
local, public, s3, rackspace, FTP и т. д. Все это возможно благодаря Flysystem.
Если вы откроете config / filesystems.php, вы увидите доступные диски и их соответствующую конфигурацию.
Загрузка файлов в Laravel
В приведенном выше разделе введения у нас есть форма с вводом файла, готовая к обработке. Мы видим, что форма указана на / process. В маршрутах / web.php мы определяем новый маршрут POST / процесса.
use Illuminate\Http\Request;
Route::post('process', function (Request $request) {
$path = $request->file('photo')->store('photos');
dd($path);
});
Вышеприведенный код выполняет захват поля фотографии из запроса и сохраняет его в папке с фотографиями. dd () - это функция Laravel, которая убивает работающий скрипт и выводит аргумент на страницу. Для меня файл был сохранен в "photos / 3hcX8yrOs2NYhpadt4Eacq4TFtpVYUCw6VTRJhfn.png". Чтобы найти этот файл в файловой системе, перейдите в хранилище / приложение, и вы найдете загруженный файл.
Если вам не нравится шаблон именования по умолчанию, предоставленный Laravel, вы можете предоставить свой, используя метод Store As.
Route::post('process', function (Request $request) {
// cache the file
$file = $request->file('photo');
// generate a new filename. getClientOriginalExtension() for the file extension
$filename ='profile-photo-' . time() . '.' . $file->getClientOriginalExtension();
// save to storage/app/photos as the new $filename
$path = $file->storeAs('photos', $filename);
dd($path);
});
После запуска вышеуказанного кода, я получил "photos / profile-photo-1517311378.png".
Разница между локальными и общедоступными дисками
В config / filesystems.php вы можете видеть диски, локальные и общедоступные. По умолчанию Laravel использует конфигурацию локального диска. Основное различие между локальным и общедоступным диском состоит в том, что локальный является частным и не может быть доступен из браузера, в то время как общедоступный может быть доступен из браузера.
Поскольку публичный диск находится в хранилище / app / public, а корневой каталог сервера Laravel публичный, вам необходимо связать хранилище / app / public с публичной папкой Laravel. Мы можем сделать это с нашим верным мастером, запустив php artisan storage: link.
Загрузка нескольких файлов
Поскольку Laravel не предоставляет функцию для загрузки нескольких файлов, мы должны сделать это сами. Это не сильно отличается от того, что мы делали до сих пор, нам просто нужен цикл.
Во-первых, давайте обновим наш вход для загрузки файлов, чтобы принимать несколько файлов.
<input type="file" name="photos[]" id="photo" multiple>
Когда мы пытаемся обработать этот файл $ request-> ('photos'), это теперь массив экземпляров UploadedFile, поэтому нам нужно перебрать массив и сохранить каждый файл.
Route::post('process', function (Request $request) {
$photos = $request->file('photos');
$paths = [];
foreach ($photos as $photo) {
$extension = $photo->getClientOriginalExtension();
$filename ='profile-photo-' . time() . '.' . $extension;
$paths[] = $photo->storeAs('photos', $filename);
}
dd($paths);
});
После выполнения этого я получил следующий массив, так как я загрузил GIF и PNG:
array:2 [?
0 => "photos/profile-photo-1517315875.gif"
1 => "photos/profile-photo-1517315875.png"
]
Проверка загрузки файлов
Проверка для загрузки файлов чрезвычайно важна. Помимо предотвращения загрузки пользователями неправильных типов файлов, это также для безопасности. Позвольте мне привести пример, касающийся безопасности. Есть опция конфигурации PHP cgi.fix_pathinfo = 1. Что это делает, когда он сталкивается с файлом, как
https://site.com/images/evil.jpg/nonexistent.php, PHP будет предполагать, что nonexistent.php является файлом PHP, и попытается запустить его. Когда он обнаруживает, что nonexistent.php не существует, PHP будет похож на «Мне нужно исправить это как можно скорее» и попытаться выполнить evil.jpg (файл PHP, замаскированный под JPEG). Поскольку evil.jpg не был проверен при загрузке, у хакера теперь есть скрипт, который он может свободно запускать вживую на вашем сервере ... Не ... хорошо.
Для проверки файлов в Laravel есть много способов, но давайте придерживаться проверки контроллера.
Route::post('process', function (Request $request) {
// validate the uploaded file
$validation = $request->validate([
'photo' => 'required|file|image|mimes:jpeg,png,gif,webp|max:2048'
// for multiple file uploads
// 'photo.*' => 'required|file|image|mimes:jpeg,png,gif,webp|max:2048'
]);
$file = $validation['photo']; // get the validated file
$extension = $file->getClientOriginalExtension();
$filename ='profile-photo-' . time() . '.' . $extension;
$path = $file->storeAs('photos', $filename);
dd($path);
});
Для приведенного выше фрагмента мы попросили Laravel убедиться, что поле с именем фотографии является обязательным, успешно загруженный файл, это изображение, оно имеет один из определенных типов пантомимы и его максимальный размер составляет 2048 килобайт ~~ 2 мегабайт.
Теперь, когда злонамеренный пользователь загружает замаскированный файл, файл не пройдет проверку, и если по какой-то странной причине вы оставите cgi.fix_pathinfo включенным, это не средство, с помощью которого вы можете получить PWNED !!!
Если вы перейдете на страницу проверки Laravel, вы увидите целую кучу правил проверки.
Перемещение файлов в облако
Итак, ваш сайт теперь взрослый, на нем много посетителей, и вы решили, что пришло время перейти в облако. Или, возможно, с самого начала вы решили, что ваши файлы будут жить на отдельном сервере. Хорошая новость заключается в том, что Laravel поставляется с поддержкой многих облачных провайдеров, но для этого урока давайте придерживаться Amazon.
Ранее мы устанавливали league / flysystem-aws-s3-v3 через композитор. Laravel будет автоматически искать его, если вы решите использовать Amazon S3 или выбросить исключение.
Чтобы загрузить файлы в облако, просто используйте:
$request->file('photo')->store('photos', 's3');
Для нескольких загрузок файлов:
foreach ($photos as $photo) {
$extension = $photo->getClientOriginalExtension();
$filename ='profile-photo-' . time() . '.' . $extension;
$paths[] = $photo->storeAs('photos', $filename, 's3');
}
Примечание: вам нужно настроить учетные данные Amazon s3 в config / filesystems.php **. **
Отправка файлов в виде вложений электронной почты
Прежде чем мы это сделаем, давайте быстро настроим нашу почтовую среду. В файле .env вы увидите этот раздел
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
Нам нужны имя пользователя и пароль, которые мы можем получить на Mailtrap.io. Mailtrap действительно хорош для тестирования электронных писем во время разработки, так как вам не нужно переполнять вашу электронную почту спамом. Вы также можете делиться почтовыми ящиками с членами команды или создавать отдельные почтовые ящики.
Сначала создайте учетную запись и войдите в систему:
- Создать новый почтовый ящик
- Нажмите, чтобы открыть почтовый ящик
- Скопируйте имя пользователя и пароль в разделе SMTP
После копирования учетных данных мы можем изменить .env на:
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=8a1d546090493b
MAIL_PASSWORD=328dd2af5aefc3
MAIL_ENCRYPTION=null
Не пытайтесь использовать мой, я удалил его.
Создайте свой почтовый ящик
php artisan make:mail FileDownloaded
Затем отредактируйте метод сборки и измените его на:
public function build()
{
return $this->from('[email protected]')
->view('emails.files_downloaded')
->attach(storage_path('app/file.txt'), [
'as' => 'secret.txt'
]);
}
Как видно из метода выше, мы передаем абсолютный путь к файлу в метод attach () и передаем необязательный массив, в котором мы можем изменить имя вложения или даже добавить пользовательские заголовки. Далее нам нужно создать нашу электронную почту.
Создайте новый файл представления в resources / views / emails / files_downloaded.blade.php и разместите содержимое ниже.
<h1>Only you can stop forest fires</h1>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Labore at reiciendis consequatur, ea culpa molestiae ad minima est quibusdam ducimus laboriosam dolorem, quasi sequi! Atque dolore ullam nisi accusantium.Tenetur!</p>
Теперь в маршрутах / web.php мы можем создать новый маршрут и вызвать почту, когда мы его посетим.
use App\Mail\FileDownloaded;
Route::get('mail', function () {
$email ='[email protected]';
Mail::to($email)->send(new FileDownloaded);
dd('done');
});
Если вы отправитесь в Mailtrap, вы должны это увидеть.
Фасад хранилища, когда файлы уже существуют
В приложении это не каждый раз, когда мы обрабатываем файлы с помощью загрузки. Иногда мы решаем отложить загрузку облачных файлов до завершения определенного действия пользователя. В других случаях у нас есть файлы на диске, прежде чем перейти к облачному провайдеру.
В такие времена Laravel предоставляет удобный складской фасад. Для тех, кто не знает, фасады в Laravel - это псевдонимы классов. Так что вместо того, чтобы делать что-то вроде
SymfonyFileWh независимо от LongLamespaceUploadedFile, мы можем вместо этого сделать хранилище.
Выбор диска для загрузки файла. Если диск не указан, Laravel ищет файл config / filesystems.php и использует диск по умолчанию.
Storage::disk('local')->exists('file.txt');
использовать облачный провайдер по умолчанию
// Storage::disk('cloud')->exists('file.txt'); will not work so do:
Storage::cloud()->exists('file.txt');
Создать новый файл с содержимым
Storage::put('file.txt', 'Contents');
Prepend to file
Storage::prepend('file.txt', 'Prepended Text');
Добавить в файл
Storage::append('file.txt', 'Prepended Text');
Получить содержимое файла
Storage::get('file.txt')
Проверьте, существует ли файл
Storage::exists('file.txt')
Принудительно загрузить файл
Storage::download('file.txt', $name, $headers); // $name and $headers are optional
Создать общедоступный URL
Storage::url('file.txt');
Создайте временный общедоступный URL-адрес (то есть файлы, которые не будут существовать после установленного времени). Это будет работать только для облачных провайдеров, поскольку Laravel еще не знает, как обрабатывать временные URL-адреса для локального диска.
Storage::temporaryUrl('file.txt', now()->addMinutes(10));
Получить размер файла
Storage::size('file.txt');
Дата последнего изменения
Storage::lastModified('file.txt')
Копировать файлы
Storage::copy('file.txt', 'shared/file.txt');
Переместить файлы
Storage::move('file.txt', 'secret/file.txt');
Удалить файлы
Storage::delete('file.txt');
// to delete multiple files
Storage::delete(['file1.txt', 'file2.txt']);
Манипулирование файлами
Изменение размера изображений, добавление фильтров и т. Д. Именно здесь Laravel нуждается во внешней помощи. Добавление этой функции в Laravel приведет только к расширению приложения, поскольку оно не требуется для установки. Нам нужен пакет под названием интервенция / изображение. Мы уже установили этот пакет, но для справки.
composer require intervention/image
Поскольку Laravel может автоматически обнаруживать пакеты, нам не нужно ничего регистрировать.
Чтобы изменить размер изображения
$image = Image::make(storage_path('app/public/profile.jpg'))->resize(300, 200);
Не забывайте каталоги
Laravel также предоставляет удобных помощников для работы с каталогами. Все они основаны на итераторах PHP, поэтому они обеспечивают максимальную производительность.
Чтобы получить все файлы:
Storage::files
Получить все файлы в каталоге, включая файлы в подпапках
Storage::allFiles($directory_name);
Чтобы получить все каталоги в каталоге
Storage::directories($directory_name);
Получить все каталоги в каталоге, включая файлы в подкаталогах
Storage::allDirectories($directory_name);
Сделать каталог
Storage::makeDirectory($directory_name);
Удалить каталог
Storage::deleteDirectory($directory_name);
Предыдущая: Laravel (5.7) События
Далее: Laravel (5.7) Почта
Новый контент: Composer: менеджер зависимостей для PHP , R программирования