Лаб. работа 6 “Работа с файлами (эмуляция S3-хранилища)”
Тема: Реализация загрузки, хранения и управления файлами с использованием локального хранилища в качестве эмуляции S3.
Цель: Научиться работать с файловой системой Laravel, имитируя облачное хранилище, и реализовать CRUD для мультимедийных данных.
Задачи
- Настроить фейковый S3-диск для локальной разработки.
- Реализовать загрузку файлов к постам.
- Добавить валидацию и оптимизацию файлов.
- Организовать просмотр и удаление файлов.
Методическая часть
1. Настройка файлового хранилища
Добавьте новый диск в
config/filesystems.php
:Обновите
.env
:Создайте директорию и симлинк:
2. Модификация модели и миграции
Создайте модель
Media
:Добавьте поля в миграцию:
Добавьте связь в модели:
В
Post.php
:
3. Обновление контроллера PostController
Метод
store
для загрузки файлов:use Illuminate\Support\Facades\Storage; public function store(Request $request) { $validated = $request->validate([ 'title' => 'required|max:255', 'files.*' => 'file|mimes:jpg,png,pdf,mp4|max:5120', ]); $post = Post::create($validated); if ($request->hasFile('files')) { foreach ($request->file('files') as $file) { $path = $file->store("posts/{$post->id}", 's3-fake'); Media::create([ 'post_id' => $post->id, 'path' => $path, 'type' => $file->getMimeType(), ]); } } return redirect()->route('posts.index'); }
Метод
destroyFile
для удаления:
4. Blade-шаблоны
Форма загрузки файлов (
posts/create.blade.php
):<form method="POST" action="{{ route('posts.store') }}" enctype="multipart/form-data"> @csrf <div class="mb-4"> <label>Прикрепить файлы:</label> <input type="file" name="files[]" multiple class="border p-2 w-full"> @error('files.*') <div class="text-red-500">{{ $message }}</div> @enderror </div> <!-- Остальные поля формы --> </form>
Галерея файлов (
posts/show.blade.php
):<div class="grid grid-cols-3 gap-4"> @foreach ($post->media as $media) <div class="relative"> @if (Str::startsWith($media->type, 'image')) <img src="{{ Storage::disk('s3-fake')->url($media->path) }}" class="w-full h-48 object-cover"> @else <div class="bg-gray-100 p-4"> <p>{{ basename($media->path) }}</p> </div> @endif <form method="POST" action="{{ route('posts.deleteFile', $media) }}" class="absolute top-2 right-2"> @csrf @method('DELETE') <button type="submit" class="bg-red-500 text-white p-1 rounded">×</button> </form> </div> @endforeach </div>
Индивидуальные задания
1. Валидация имен файлов
Запретите загрузку файлов с пробелами в имени:
2. Логирование операций
Создайте middleware
LogFileOperations
:Зарегистрируйте его в
bootstrap/app.php
:
3. Оптимизация изображений (опционально)
Установите пакет:
Оптимизируйте изображения перед сохранением:
Проверка работы
- Загрузка файлов:
- Откройте форму создания поста.
- Загрузите несколько файлов (изображения, PDF).
- Убедитесь, что файлы сохранились в
storage/app/s3-fake/posts/{post_id}
.
- Откройте форму создания поста.
- Просмотр файлов:
- Откройте страницу поста.
- Проверьте, что изображения отображаются, а PDF показывается как ссылка.
- Откройте страницу поста.
- Удаление файлов:
- Нажмите кнопку удаления файла.
- Убедитесь, что файл удалён из хранилища и БД.
- Нажмите кнопку удаления файла.
Примечания
- Преимущества подхода:
- Эмуляция облачного хранилища экономит ресурсы.
- Легко переключиться на реальный S3 через
.env
.
- Эмуляция облачного хранилища экономит ресурсы.
- Важно:
- Для продакшена замените
s3-fake
наs3
в.env
.
- Для тестирования используйте
Storage::fake('s3-fake')
.
- Для продакшена замените