Неразрешимая зависимость при обработке загрузок изображений с заданиями laravel - PullRequest
0 голосов
/ 09 марта 2019

Каждое загруженное изображение создает еще четыре изображения для разных экранов, а затем переносится в пространство в Digital Ocean. Так что это очень много времени. Поэтому я хочу использовать функцию Laravels Job. Вот как это выглядит сейчас:

ImageController:

public function uploadMultiple($vehicle_id, Request $request)
{
    $this->setVehicle($vehicle_id);
    $this->validate($request, [
        'images'    => 'required',
        'images.*'  => 'image'
    ]);
    foreach ($request->images as $image){
        $this->uploadSingleImage($image);
    }
    \Alert::success('Bilder wurden hochgeladen')->flash();

    return redirect()->back();
}

protected function uploadSingleImage(UploadedFile $image)
{
    VehicleImageUploaderJob::dispatch($this->getVehicle());
}

VehicleImageUploaderJob:

public function handle(UploadedFile $image)
{
    $disk = FilesystemHelper::getDisk('producerData');
    $originalName = basename($image->getClientOriginalName(), '.'.$image->getClientOriginalExtension());
    $extension = $image->getClientOriginalExtension();

    $dbImage = new Image();

    // Store image in original size
    $path = $image->storeAs(
        'producers/' . $this->getVehicle()->producer->id . '/vehicles/' . $this->getVehicle()->id, // Folder or Directory
        $image->getClientOriginalName(), // File Name
        $disk // Disk
    );
    Storage::disk($disk)->setVisibility($path, 'public');

    $dbImage->original = $path;
    $dbImage->disk = $disk;

    $file = ImageManipulator::make($image);

    foreach(config('images.vehicles.formats') as $format => $values){
        $file->backup();
        $fileName = $originalName . '-' . str_random(6) . '-' . $values['width'] . 'x' . $values['height'] . '.' . $extension;
        if($format === 'thumbnail'){
            $file->fit($values['width'],$values['height'])
                ->save();
        } else {
            $file->fit($values['width'], $values['height'], function ($constraint) {
                $constraint->aspectRatio();
                $constraint->upsize();
            })->save();
        }
        $path = $image->storeAs(
            'producers/' . $this->getVehicle()->producer->id . '/vehicles/' . $this->getVehicle()->id, // Folder or Directory
            $fileName, // File Name
            $disk // Disk
        );

        Storage::disk($disk)->setVisibility($path, 'public');
        $dbImage->{$format} = $path;
        $file->reset();
    }

    $dbImage->save();
    $this->getVehicle()->images()->attach($dbImage->id);
    $this->getVehicle()->save();
}

К сожалению, я получаю сообщение об ошибке каждый раз, когда я хочу загрузить изображение (в настоящее время драйвер очереди «синхронизируется»): Разрешение неразрешимой зависимости [Параметр # 0 [строка $ path]] в классе Symfony \ Component \ HttpFoundation \ File \ UploadedFile

Может быть, потому что я должен передать изображение, а не автомобиль. Транспортное средство ожидается в конструкторе, а изображение - в методе handle. Но когда я передаю изображение, оно выдает ошибку, говоря, что ожидает экземпляр Vehicle.

1 Ответ

1 голос
/ 10 марта 2019

Проблема заключалась в том, что UploadedFile (то, что вы получаете из запроса на загрузку) не сериализуем и поэтому не может быть обработан заданием.Поэтому мне пришлось создать новую модель + таблицу для временного хранения изображения.

Способ изображения следующий:

  • храниться локально как файл
  • создать новый экземпляр временной модели
  • передать эту модель в задание
  • заново создать изображение типа UploadedFile и обработать изображение (создать четыре разрешения и загрузить его в цифровой океан)
  • удалить локальный файл
  • удалить временную модель

Новая модель:

use App\DBEntities\MasterEntity;

class VehicleImageForJob extends MasterEntity
{
    protected $guarded = ['id'];
}

Новая таблица:

class CreateVehicleImageForJobsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('vehicle_image_for_jobs', function (Blueprint $table) {
            $table->increments('id');
            $table->string('file');
            $table->string('mime_type');
            $table->string('original_name');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('vehicle_image_for_jobs');
    }
}

Новый диск вfilesystem.php:

'vehicle_image_temp' => [
    'driver' => 'local',
    'root' => storage_path('app/vehicle_images/temp')
]

Модифицированный контроллер:

protected function uploadSingleImage(UploadedFile $image)
{
    $disk = 'vehicle_image_temp';

    $path = $image->store("/", [
        'disk' => $disk
    ]);

    $vehicleImageForJob = VehicleImageForJob::create([
        'file' => $path,
        'mime_type' => $image->getMimeType(),
        'original_name' => $image->getClientOriginalName()
    ]);

    VehicleImageUploaderJob::dispatch($vehicleImageForJob, $this->getVehicle());
}

Модифицированное задание:

class VehicleImageUploaderJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $vehicle;
    protected $image;

    protected $disk = 'vehicle_image_temp';

    /**
     * VehicleImageUploaderJob constructor.
     * @param VehicleImageForJob $image
     * @param Vehicle $vehicle
     */
    public function __construct(VehicleImageForJob $image, Vehicle $vehicle)
    {
        $this->vehicle = $vehicle;
        $this->image = $image;
    }

    /**
     * @param UploadedFile $image
     * @throws \Exception
     */
    public function handle()
    {
        $image = new UploadedFile(storage_path("app/vehicle_images/temp/{$this->image->file}"),
            $this->image->original_name,
            $this->image->mime_type,
            null,
            null,
            true
        );

        $disk = FilesystemHelper::getDisk('producerData');
        $originalName = basename($image->getClientOriginalName(), '.'.$image->getClientOriginalExtension());
        $extension = $image->getClientOriginalExtension();

        $dbImage = new Image();

        // Store image in original size
        $path = $image->storeAs(
            'producers/' . $this->getVehicle()->producer->id . '/vehicles/' . $this->getVehicle()->id, // Folder or Directory
            $image->getClientOriginalName(), // File Name
            $disk // Disk
        );
        Storage::disk($disk)->setVisibility($path, 'public');

        $dbImage->original = $path;
        $dbImage->disk = $disk;

        $file = ImageManipulator::make($image);

        foreach(config('images.vehicles.formats') as $format => $values){
            $file->backup();
            $fileName = $originalName . '-' . str_random(6) . '-' . $values['width'] . 'x' . $values['height'] . '.' . $extension;
            if($format === 'thumbnail'){
                $file->fit($values['width'],$values['height'])
                    ->save();
            } else {
                $file->fit($values['width'], $values['height'], function ($constraint) {
                    $constraint->aspectRatio();
                    $constraint->upsize();
                })->save();
            }
            $path = $image->storeAs(
                'producers/' . $this->getVehicle()->producer->id . '/vehicles/' . $this->getVehicle()->id, // Folder or Directory
                $fileName, // File Name
                $disk // Disk
            );

            Storage::disk($disk)->setVisibility($path, 'public');
            $dbImage->{$format} = $path;
            $file->reset();
        }

        $dbImage->save();
        $this->getVehicle()->images()->attach($dbImage->id);
        $this->getVehicle()->save();

        Storage::disk($this->disk)->delete($this->image->file);
        $this->image->delete();
    }

    protected function getVehicle(): Vehicle
    {
        if($this->vehicle instanceof Vehicle){
            return $this->vehicle;
        } else {
            throw new \Exception("Vehicle not set on ImageUploaderJob");
        }
    }
}
...