Home > Software design >  Symfony 5 Rest, Base64 encoded file to DTO with validation as File object
Symfony 5 Rest, Base64 encoded file to DTO with validation as File object

Time:10-13

I have a PostController looking like this:

 #[Route(name: 'add', methods: ['POST'])]
 public function addPost(Request $request): JsonResponse
 {
    /** @var PostRequestDto $postRequest */
    $postRequest = $this->serializer->deserialize(
        $request->getContent(),
        PostRequestDto::class,
        'json'
    );

    return $this->postService->addPost($postRequest);
}

PostService:

public function addPost(PostRequestDto $request): JsonResponse
{
    $errors = $this->validator->validate($request);
    if (count($errors) > 0) {
        throw new ValidationHttpException($errors);
    }

    #...

    return new JsonResponse(null, Response::HTTP_CREATED);
}

And PostRequestDto:

class PostRequestDto
{
    #[Assert\NotBlank]
    #[Assert\Length(max: 250)]
    private ?string $title;

    #[Assert\NotBlank]
    #[Assert\Length(max: 1000)]
    private ?string $article;

    #[Assert\NotBlank]
    #[Assert\Image]
    private ?File $photo;

    #[Assert\NotBlank]
    #[Assert\GreaterThanOrEqual('now', message: 'post_request_dto.publish_date.greater_than_or_equal')]
    private ?DateTimeInterface $publishDate;
}

My Postman request looks like this:

{
    "title": "Test",
    "article": "lorem ipsum....",
    "photo": "base64...",
    "publishDate": "2021-10-15 08:00:00"
}

As you can see from postman request, I'm sending base64 encoded file. Now, in the controller I want to deserialize it to match with PostRequestDto so I can validate it as a File in the PostService - how can I achieve this ?

CodePudding user response:

I don't know how exactly your serializer ($this->serializer) is configured, but I think you have to adjust/add your normilizer with Symfony\Component\Serializer\Normalizer\DataUriNormalizer

// somewhere in your controller/service where serilaizer is configured/set
$normalizers = [
   //... your other normilizers if any
   new DataUriNormalizer(), // this one
   ];
$encoders = [new JsonEncoder()];

$this->serializer = new Serializer($normalizers, $encoders);

If you look inside DataUriNormalizer you'll see, it works with File which is exactly what you have in your PostRequestDto

The only thing to be aware of → format of base64. If you follow the link of denormilize() method, you will see it expects data:image/png;base64,... So it has to start with data:... and you probably have to change your postman-json-payload to

{
    "title": "Test",
    "article": "lorem ipsum....",
    "photo": "data:<your_base64_string>",
    "publishDate": "2021-10-15 08:00:00"
}

Since you work with images, I would also send the mime-type. Like:

"photo": "data:image/png;base64,<your_base64_string>",
  • Related