API Platform

API Platform Admin – resize images after upload

It has been quite some time since I wanted to write something (anything) about API Platform. I’ve been playing with it for a couple of months for a medium sized project and I’m very satisfied. Its only disadvantage is it has a long learning curve. 

API Platform is the best way to create REST/GraphQL APIs, in PHP at least.

I encountered a lot of problems because I did not know the technology but I was too busy to write about them. Now I’m making an exception.

So the issue is with the out of the box admin that comes with API Platform. A quite standard feature of any image uploading system is it has to resize the image to a certain size. I cannot stress this enough, a high quality API does not serve files of any size.

Now I’m gonna assume you have a standard API Platform installation – I’m using version v2.6.8 without Docker but like the version with Docker (autowiring and stuff). The reason is I’m not using Docker in production either and locally I have exactly the same OS and other software and configs just like production.

Next I’m gonna assume you’re performing an image upload in the Admin using the VichUploaderBundle – basically the section of the documentation called Uploading to an Existing Resource with its Fields.

At the moment of this writing that section does not describe how to resize the image after the upload.

To resize the image we need to do two things: 

1. Create a subscriber that hooks into the Vich’s bundle event.

2. Populate the subscriber with the resizing image feature using Imagine.

As you can see, I’m not reinventing the wheel, I’m just using the standard way of doing things.

If we analyze the UploadHandler class of VichUploaderBundle we see it emits an event: Vich\UploaderBundle\Event\Events::POST_UPLOAD after the upload. So we need to hook into the subscriber to listen to this event.

Without wasting anymore time the subscriber looks like:

<?php

namespace App\EventSubscriber;

use ApiPlatform\Core\EventListener\EventPriorities;
use App\Constants\Constants;
use App\Entity\Banner;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Vich\UploaderBundle\Event\Event;
use Vich\UploaderBundle\Event\Events;
use Imagine\Gd\Imagine;
use Imagine\Image\Box;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

final class VichFileUploadSubscriber implements EventSubscriberInterface
{
    private $imagine;

    private $parameterBag;

    public function __construct(ParameterBagInterface $parameterBag)
    {
        $this->imagine = new Imagine();
        $this->parameterBag = $parameterBag;
    }

    public static function getSubscribedEvents()
    {
        return [
            Events::POST_UPLOAD => ['handleResize', EventPriorities::POST_WRITE],
        ];
    }

    public function handleResize(Event $event): void
    {
        $entity = $event->getObject();
        if ($entity instanceof Banner) {
            $maxWidth = Constants::MAX_BANNER_WIDTH;
            $maxHeight = Constants::MAX_BANNER_HEIGHT;
            $this->resizeImage($entity, $maxWidth, $maxHeight);
        }
    }

    private function resizeImage($entity, $maxWidth, $maxHeight)
    {
        $kernelDir = $this->parameterBag->get('kernel.project_dir');
        $fileName = $kernelDir . '/public/media/' . $entity->getFile()->getFileName();

        list($iwidth, $iheight) = getimagesize($fileName);
        $ratio = $iwidth / $iheight;
        $width = $maxWidth;
        $height = $maxHeight;
        if ($width / $height > $ratio) {
            $width = $height * $ratio;
        } else {
            $height = $width / $ratio;
        }

        $photo = $this->imagine->open($fileName);
        $photo->resize(new Box($width, $height))->save($fileName);
    }
}

So this is it basically. I hope you will visit the links provided in order to learn better how to work with API Platform. It is a complex software that requires time to master.

And don’t worry, it’s been months already and I’m not mastering it.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.