Symfony 5 Rest,Base64 编码文件到 DTO,验证为文件对象

Symfony 5 Rest, Base64 encoded file to DTO with validation as File object

我有一个 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;
}

我的 Postman 请求如下所示:

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

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

我不知道你的序列化器 ($this->serializer) 是如何配置的,但我认为你必须 adjust/add 你的规范化器 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() 方法的 link,你会看到它期望 data:image/png;base64,... 所以它必须以 data:... 开头,您可能必须将邮递员-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>",