首页 > 解决方案 > Symfony 5 Rest,Base64 编码文件到 DTO,验证为 File 对象

问题描述

PostController看起来像这样:

 #[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);
}

并且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;
}

我的邮递员请求如下所示:

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

正如您从邮递员请求中看到的那样,我正在发送base64编码文件。现在,在控制器中我想反序列化它以匹配,PostRequestDto所以我可以将它验证为File-PostService我怎样才能实现这一点?

标签: restfilesymfonybase64dto

解决方案


我不知道你的序列化器($this->serializer)是如何配置的,但我认为你必须调整/添加你的规范化器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);

如果你往里面DataUriNormalizer看,你会看到,它可以与File你在你的PostRequestDto

唯一需要注意的 → base64 的格式。如果您按照方法的链接denormilize()您会看到它期望data:image/png;base64,... 所以它必须开始,data:...您可能必须将您的 postman-json-payload 更改为

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

由于您使用图像,因此我还会发送 mime 类型。喜欢:

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

推荐阅读