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
我遇到了同样的问题,并且 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] : [];
}
}