VichUploaderBundle ContentUrl 未显示在响应正文 Symfony 7 上

问题描述 投票:0回答:1
vich_uploader:
db_driver: orm
metadata:
    type: attribute
mappings:
    media_object:
        uri_prefix: /media
        upload_destination: '%kernel.project_dir%/public/media'
        # Will rename uploaded files using a uniqueid as a prefix.
        namer: Vich\UploaderBundle\Naming\OrignameNamer

这是创建的 VichUploader.yaml 文件,与 ApiPlatform 文档中的内容相同

<?php

declare(strict_types=1);

namespace App\Entity;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\OpenApi\Model;
use App\Controller\CreateMediaObjectAction;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

#[Vich\Uploadable]
#[ORM\Entity]
#[ApiResource(
types: ['https://schema.org/MediaObject'],
operations: [
    new Get(),
    new GetCollection(),
    new Post(
        controller: CreateMediaObjectAction::class,
        openapi: new Model\Operation(
            requestBody: new Model\RequestBody(
                content: new \ArrayObject([
                    'multipart/form-data' => [
                        'schema' => [
                            'type' => 'object',
                            'properties' => [
                                'file' => [
                                    'type' => 'string',
                                    'format' => 'binary'
                                ]
                            ]
                        ]
                    ]
                ])
            )
        ),
        validationContext: ['groups' => ['Default', 'media_object_create']],
        deserialize: false
    )
],
normalizationContext: ['groups' => ['media_object:read']]
)]
class MediaObject
{
#[ORM\Id, ORM\Column, ORM\GeneratedValue]
private ?int $id = null;

#[ApiProperty(types: ['https://schema.org/contentUrl'])]
#[Groups(['media_object:read'])]
public ?string $contentUrl = null;

#[Vich\UploadableField(mapping: "media_object", fileNameProperty: "filePath")]
#[Assert\NotNull(groups: ['media_object_create'])]
public ?File $file = null;

#[ORM\Column(nullable: true)]
public ?string $filePath = null;

public function getId(): ?int
{
    return $this->id;
}
}

这是我的 MediaObject.php 实体,创建方式与 ApiPlatform 文档中所述相同

<?php

declare(strict_types=1);

namespace App\Serializer;

use App\Entity\MediaObject;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
use Vich\UploaderBundle\Storage\StorageInterface;

final class MediaObjectNormalizer implements 
NormalizerAwareInterface
{
use NormalizerAwareTrait;

private const ALREADY_CALLED = 'MEDIA_OBJECT_NORMALIZER_ALREADY_CALLED';

public function __construct(private StorageInterface $storage)
{
}

public function normalize($object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
{
    $context[self::ALREADY_CALLED] = true;

    $object->contentUrl = $this->storage->resolveUri($object, 'file');

    return $this->normalizer->normalize($object, $format, $context);
}

public function supportsNormalization($data, ?string $format = null, array $context = []): bool
{
    if (isset($context[self::ALREADY_CALLED])) {
        return false;
    }

    return $data instanceof MediaObject;
}
}

这是我的 MediaObjectNormalizer.php 文件,位于 Serializer 文件夹中,所有内容都是使用官方 ApiPlatform.com 文档创建和复制/粘贴的,但当我发布(上传)文件和在 swagger 上获取文件时,我仍然遇到这个问题,没有显示 ContentUrl

symfony api-platform.com
1个回答
0
投票

我遇到了同样的问题,并且 Api Plattform 文档中的 MediaObjectNormalizer 实现不起作用。

这就是我实现的并且有效:

namespace App\Serializer;


use App\Entity\MediaObject;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Vich\UploaderBundle\Storage\StorageInterface;

#[AsDecorator('api_platform.jsonld.normalizer.item')]
final class MediaObjectNormalizer implements NormalizerInterface, SerializerAwareInterface
{
    private const ALREADY_CALLED = 'MEDIA_OBJECT_NORMALIZER_ALREADY_CALLED';

    public function __construct(
        private StorageInterface $storage,
        private NormalizerInterface $normalizer
    )
    {
    }

    public function normalize($object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
    {
        $context[self::ALREADY_CALLED] = true;

        $object->contentUrl = $this->storage->resolveUri($object, 'file');

        return $this->normalizer->normalize($object, $format, $context);
    }

    public function supportsNormalization($data, ?string $format = null, array $context = []): bool
    {
        if (isset($context[self::ALREADY_CALLED])) {
            return false;
        }

        return $data instanceof MediaObject;
    }

    public function setSerializer(SerializerInterface $serializer): void
    {
        if ($this->normalizer instanceof SerializerAwareInterface) {
            $this->normalizer->setSerializer($serializer);
        }
    }

    public function getSupportedTypes(?string $format): array
    {
        if (method_exists($this->normalizer, 'getSupportedTypes')) {
            return $this->normalizer->getSupportedTypes($format);
        }

        return 'jsonld' === $format ? ['*' => true] : [];
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.