nanadjei2's avatar

Uploading image with job fails

I am building an app which I want to use job to upload image to cloudinary. But I keep getting his error message:

"message": "Serialization of 'Illuminate\\Http\\UploadedFile' is not allowed", "exception": "Exception"

0 likes
13 replies
Sinnbeck's avatar

Do you mean that you want to pass a user upload using a form, to a job? Can you show some code?

nanadjei2's avatar

@sinnbeck Yeah, I am passing the image from a from to the controller and then down to the job to be sent to Cloudinary.

Sinnbeck's avatar

You cannot send the upload task itself to a job. A job takes serialized data

You need to either first save it to your server and then pass that local path to the job or take the raw file data and pass to the job.

If you showed your code I might be able to help you getting it working.

nanadjei2's avatar

My controller to store the image:

 public function store()
  {
    request()->validate(['property_id' => 'required|integer', 'images' => 'required|array', 'images.*' => "required|mimes:jpeg,bmp,jpg,png|between:1, 6000"]);

    UploadPropertyImagesJob::dispatch(request()->images);

    return $this->apiRespondWithSuccess('Image Uploaded Successfully', ["data" => Property::find(request()->property_id)]);
}

My job class:

/**
 * Create a new job instance.
 *
 * @return void
 */
public function __construct($imageFiles)
{
    $this->imageFiles = $imageFiles;
    $this->uploadDirectory = config('cloudder.propertiesDirectory');
}

/**
 * Execute the job.
 *
 * @return void
 */
public function handle()
{
    foreach ($this->imageFiles as $requestImage) {
        $requestImage->getClientOriginalName(); // Someimage.png

        $image = $requestImage->getRealPath();

        Cloudder::upload($image, null, ["folder" => $this->uploadDirectory]);

        list($width, $height) = getimagesize($image);

        $publicId = Cloudder::getPublicId();
        Cloudder::show($publicId, ["width" => $width, "height" => $height]);

        //save to uploads directory
        // $image->move(public_path("uploads"), $name);

        //Save images
        $this->saveImages($publicId, $requestImage);

        logger()->info("Image uploaded successfully");
    }
}

/**
 * This is where the saveing of the image into the databse actually happends
 * We get the image's name and save it in the db as the actual file resides in cloudinary
 * 
 * @return \App\Models\PropertyImage
 */
public function saveImages(string $publicId, $image)
{
    $imageId = str_replace($this->uploadDirectory, "", $publicId);
    PropertyImage::create([
        "property_id" => request()->property_id,
        "public_id" => $publicId,
        "url" => trim($imageId) . "." . \File::extension($image->getClientOriginalName())
    ]);
}

/**
 * When job fails report as log
 */
public function failed(\Exception $e)
{
    logger()->error($e->getMessage());
}
Sinnbeck's avatar

Ok. You can get the image temp path + names like this and pass it to your job, which can then handle those instead (be aware that these are just strings)

$images = [];
foreach (request()->images as $file) {

    $images[] = [
        'path' => $file->getRealPath(),
        'name' => $file->getClientOriginalName(),
    ];
}

UploadPropertyImagesJob::dispatch($images);;
nanadjei2's avatar

Ok thank you. But why are you saying I should be aware that those are just strings?

Sinnbeck's avatar

If you try this inside your job it will fail

foreach ($this->imageFiles as $requestImage) {
        $image = $requestImage->getRealPath();

Should be

foreach ($this->imageFiles as $requestImage) {
        $image = $requestImage['path'];
1 like
nanadjei2's avatar

Ok am getting.

`Error in sending request to server - file '/private/var/tmp/phpYylC9L' does not exist {"exception":"[object] (Cloudinary\Error(code: 0):

Error in sending request to server - file '/private/var/tmp/phpYylC9L' does not exist at /Users/nanadjei2/Desktop/Apps/leasemaster-backend/vendor/cloudinary/cloudinary_php/src/Uploader.php:496) [stacktrace]`

Sinnbeck's avatar

Ok my guess is that it has been removed in the meantime. It is just a temp file. You can get the actual content instead if you can somehow pass that to Cloudder

$images[] = [
        'content' => file_get_contents($file->getRealPath()),
        'name' => $file->getClientOriginalName(),
    ];
nanadjei2's avatar

@sinnbeck Am getting this error.

"message": "Unable to JSON encode payload. Error code: 5", "exception": "Illuminate\Queue\InvalidPayloadException",

Sinnbeck's avatar

Not sure why. Maybe it's to big. Are you not getting any extra information?

prshost's avatar

This is the only way it works. \App\Jobs\YourClass::dispatchNow();

Please or to participate in this conversation.