REST API and upload images

Foreword

In some cases you must add images in Your REST API application for example when you want implement possibility to add photo to announcement, event etc. In this case reasonable solution is division endpoint to upload image.

Assumptions

We assumed to create separate endpoint to upload images. One solution is to use a base64, specification might look like this:

POST http://server/data/media
body:
{
      "data": "data:image/jpeg;base64,/9j/4AAQSkZJ..."
}

The response should return the ID of uploaded image to link with other entity.

201 Created
Location: http://server/data/media/21323
body:
{
      "id": 21323
}

Implementation with Symfony

Below service to decode and save image.

class FileUploadService
{
    private $uploadDir;

    public function __construct($uploadDir)
    {
        $this->uploadDir = $uploadDir;
    }

    public function base64Decode($base64)
    {
        return base64_decode($base64);
    }

    public function upload($originalFileName, $image)
    {
        $originalFilePath = sprintf('%s/%s', $this->uploadDir, $originalFileName);

        return file_put_contents($originalFilePath, $image) == false ? false : true;
    }
}

And ImageController

class ImageController
{
    const IMAGE_TYPE = 'jpg';

    public function uploadAction(Request $request)
    {

        $form = $this->createForm(FileType::class);

        $submittedData = json_decode($request->getContent(), true);
        $form->submit($submittedData);

        if (!$form->isValid()) {
            return $this->error($this->getFormErrorsAsArray($form));
        }

        /** @var File $file */
        $file = $form->getData();

        $fileName = sprintf('%s.%s', Uuid::uuid4()->toString(), self::IMAGE_TYPE);

        /** @var FileUploadService $fileUploadService */
        $fileUploadService = $this->get('accessibility_barriers.services.file_upload_service');

        $imageFile = $fileUploadService->base64Decode($file->data);
        $fileUploadService->upload($fileName, $imageFile);

        $image = new Image();
        $image->setName($fileName);

        $em = $this->getDoctrine()->getManager();
        $em->persist($image);
        $em->flush();

        return $this->success($image, 'Image', Response::HTTP_CREATED, array('IMAGE_BASIC'));
    }