Использование Cloudinary с пакетом Laravel spatie / media-library

Кто-нибудь использует пакет Laravel spatie / media-library с Cloudinary?
Я думал, что реализовать его с помощью flysystem будет тривиально.
На самом деле я использую Cloudinary как поле Nova с silvanite / nova-field-cloudinary, и он работает отлично, но мне нужна медиа-библиотека, которая не поддерживает его из коробки.

Итак, что я сделал:
- добавил облачный диск:

'cloudinary' => [
    'driver' => 'cloudinary',
    'api_key' => env('CLOUDINARY_API_KEY'),
    'api_secret' => env('CLOUDINARY_API_SECRET'),
    'cloud_name' => env('CLOUDINARY_CLOUD_NAME'),
    'url' => env('CLOUDINARY_URL'),
],
  • изменил имя диска на облачный

    'disk_name' => 'cloudinary',
    
  • попытался добавить изображение

    $newMedia = $myModel
        ->addMediaFromUrl($imageUrl)
        ->setFileName($filename)
        ->toMediaCollection();
    

а затем я получаю сообщение об ошибке «Файл не найден». Изображение загружено, но запись не сохраняется в БД.

#message: "File not found at path: 711297/my-image.jpg"
#code: 0
#file: "./vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php"
#line: 435
-previous: League\Flysystem\FileNotFoundException^ {#2389
#path: "711297/my-image.jpg"
#message: "File not found at path: 711297/my-image.jpg"
#code: 0
#file: "./vendor/league/flysystem/src/Filesystem.php"
#line: 389
trace: {
./vendor/league/flysystem/src/Filesystem.php:389 { …}
./vendor/league/flysystem/src/Filesystem.php:194 { …}
./vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php:433 { …}
./vendor/spatie/laravel-medialibrary/src/Filesystem/Filesystem.php:81 { …}
./vendor/spatie/laravel-medialibrary/src/Filesystem/Filesystem.php:88 { …}
./vendor/spatie/laravel-medialibrary/src/FileManipulator.php:77 { …}
./vendor/spatie/laravel-medialibrary/src/FileManipulator.php:44 { …}
./vendor/spatie/laravel-medialibrary/src/Filesystem/Filesystem.php:33 { …}
./vendor/spatie/laravel-medialibrary/src/FileAdder/FileAdder.php:310 { …}
./vendor/spatie/laravel-medialibrary/src/FileAdder/FileAdder.php:301 { …}
./vendor/spatie/laravel-medialibrary/src/FileAdder/FileAdder.php:251 { …}
./vendor/efdi/carmarket-module/src/Jobs/ImportImages.php:145 { …}
./vendor/efdi/carmarket-module/src/Jobs/ImportImages.php:84 { …}
./vendor/efdi/carmarket-module/src/Jobs/ImportImages.php:43 { …}

Итак, похоже, проблема в том, что он пытается загрузить изображение, используя локальный путь, который, конечно, не существует.
Я попытался использовать собственный PathGenerator, чтобы он возвращал URL-адрес, который не является решением, поскольку ожидает путь.
I не могу понять, как они это делают для S3.

Так что, если кто-нибудь знает, как решить эту проблему или имеет рабочее решение, я был бы признателен.


person praxus    schedule 21.11.2019    source источник


Ответы (1)


Это происходит потому, что пакет spatie пытается преобразовать загруженное изображение. Перейдите в файл конфигурации medialibrary.php и закомментируйте эти строки:

    'image_generators' => [
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Image::class,
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Webp::class,
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Pdf::class,
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Svg::class,
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Video::class,
    ],

Если для данного mime-типа изображения не найден генератор, изображение не будет преобразовано. Таким образом, ошибка не будет выдана. Затем конвертируйте свои изображения с помощью облачного хранилища.

Для этого я создал CloudinaryUrlGenerator, который расширяет BaseUrlGenerator.

    const HOST = 'https://res.cloudinary.com/';

    /**
     * Get the url for a media item.
     *
     * @return string
     */
    public function getUrl(): string
    {
        $cloudBaseUrl = self::HOST . config('filesystems.disks.cloudinary.cloud_name') . '/';

        $options = [
            'q_auto',
        ];

        $filePathIncludingFilenameAndExtension = '/' . $this->pathGenerator->getPath($this->media) . $this->media->file_name;

        return $cloudBaseUrl . implode(',', $options) . $filePathIncludingFilenameAndExtension;
    }

В getTemporaryUrl и getResponsiveImagesDirectoryUrl я просто вернулся: $this->getUrl().

Как только вы это сделаете, вы можете получить такие изображения:

<img src="{{ $model->media->first()->getUrl() }}" />
person Martijn Imhoff    schedule 26.11.2019
comment
Пока работает, спасибо. Я должен был знать, потому что в трассировке стека есть FileManipulator ... Кстати. мне было недостаточно закомментировать эти image_generators, у меня также был метод registerMediaConversions (), определенный в модели. - person praxus; 26.11.2019