ImageUploadService.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. <?php
  2. namespace App\Services;
  3. /*
  4. * ImageUploadService — загрузка, ресайз и хранение изображений блоков.
  5. *
  6. * Сохраняет в disk 'public' → storage/app/public/blocks/{folder}/uuid.webp
  7. * Публичный URL: asset('storage/blocks/{folder}/uuid.webp')
  8. *
  9. * Размеры из определения поля макета:
  10. * width + height → обрезать по центру (cover crop)
  11. * только width → уменьшить до ширины, сохранить пропорции
  12. * ничего → уменьшить до 1200px по ширине, сохранить пропорции
  13. *
  14. * Формат вывода всегда WebP (качество 85).
  15. */
  16. use Illuminate\Http\UploadedFile;
  17. use Illuminate\Support\Facades\Storage;
  18. use Illuminate\Support\Str;
  19. use Intervention\Image\Drivers\Gd\Driver;
  20. use Intervention\Image\ImageManager;
  21. class ImageUploadService
  22. {
  23. private ImageManager $manager;
  24. public function __construct()
  25. {
  26. $this->manager = new ImageManager(new Driver());
  27. }
  28. /**
  29. * Сохраняет загруженный файл, возвращает путь относительно диска 'public'.
  30. * Например: 'blocks/steps_section/550e8400-e29b-41d4-a716-446655440000.webp'
  31. *
  32. * @param array{width?:int, height?:int} $fieldDef — определение поля из BlockLayoutRegistry
  33. */
  34. public function store(UploadedFile $file, string $folder, array $fieldDef = []): string
  35. {
  36. $image = $this->manager->read($file->getRealPath());
  37. $w = $fieldDef['width'] ?? null;
  38. $h = $fieldDef['height'] ?? null;
  39. if ($w && $h) {
  40. // Cover-кроп: обрезаем по центру до точных размеров
  41. $image->cover($w, $h);
  42. } elseif ($w) {
  43. // Масштабируем до ширины (не увеличиваем)
  44. $image->scaleDown(width: $w);
  45. } else {
  46. // По умолчанию: не шире 1200px
  47. $image->scaleDown(width: 1200);
  48. }
  49. $filename = Str::uuid() . '.webp';
  50. $path = "blocks/{$folder}/{$filename}";
  51. Storage::disk('public')->put($path, $image->toWebp(85));
  52. return $path;
  53. }
  54. /**
  55. * Удаляет старый файл из диска 'public', если это внутренний файл (не внешний URL).
  56. */
  57. public function delete(string $oldPath): void
  58. {
  59. if ($oldPath && !str_starts_with($oldPath, 'http') && Storage::disk('public')->exists($oldPath)) {
  60. Storage::disk('public')->delete($oldPath);
  61. }
  62. }
  63. }