【发布时间】:2020-11-05 04:22:35
【问题描述】:
我正在尝试使用 Api Platform 和 Vich Uploader Bundle 上传文件。 当我发送带有 multipart/form-data 和要附加图像文件的实体 ID 的 POST 请求时,我的实体收到 200 响应。但是上传的文件不会上传到目标目录,并且它生成的文件名不会保留。没有错误,没有任何线索,不知道。
这是我的代码:
//vich uploader mappings
vich_uploader:
db_driver: orm
mappings:
logo:
uri_prefix: /logo
upload_destination: '%kernel.project_dir%/public/images/logo/'
namer: App\Infrastructure\Naming\LogoNamer
//Organization Entity
<?php
namespace App\Infrastructure\Dto;
...use
/**
* @ORM\Entity()
* @ApiResource(
* iri="https://schema.org/Organization",
* shortName="Place",
* collectionOperations={
* "post" = {
* "denormalization_context" = {
* "groups"={
* "organization:collection:post"
* }
* }
* },
* "get" = {
* "normalization_context" = {
* "groups"={
* "organization:collection:get"
* }
* }
* }
* },
* itemOperations={
* "get",
* "CreateOrganizationLogoAction::OPERATION_NAME" = {
* "groups"={"logo:post"},
* "method"="POST",
* "path"=CreateOrganizationLogoAction::OPERATION_PATH,
* "controller"=CreateOrganizationLogoAction::class,
* "deserialize"=false,
* "validation_groups"={"Default", "logo_create"},
* "openapi_context"={
* "summary"="Uploads logo file to given Organization resource",
* "requestBody"={
* "content"={
* "multipart/form-data"={
* "schema"={
* "type"="object",
* "properties"={
* "logoFile"={
* "type"="string",
* "format"="binary"
* }
* }
* }
* }
* }
* }
* }
* }
* }
* )
* @Vich\Uploadable
*/
final class Organization
{
/**
* @Groups({"organization:collection:get"})
* @ORM\Id
* @ORM\Column(type="uuid", unique=true)
* @ORM\GeneratedValue(strategy="CUSTOM")
* @ORM\CustomIdGenerator(class=UuidGenerator::class)
* @ApiProperty(identifier=true)
*/
protected Uuid $id;
/**
* @Groups({"organization:collection:get", "organization:collection:post"})
* @ORM\Column(type="string", length=100, unique=true)
*/
public string $slug;
/**
* @ORM\Column(type="smallint")
*/
public int $status;
/**
* @ApiProperty(iri="https://schema.org/name")
* @Groups({"organization:collection:get"})
* @ORM\Column(type="string", length=100, nullable=true)
*/
public ?string $title = null;
/**
* @ApiProperty(iri="http://schema.org/logo")
* @Groups({"organization:collection:get", "logo:post"})
* @ORM\Column(nullable=true)
*/
public ?string $logoPath = null;
/**
* @ApiProperty(iri="https://schema.org/description")
* @ORM\Column(type="text", nullable=true)
*/
public ?string $description = null;
/**
* @ApiProperty(iri="https://schema.org/disambiguatingDescription")
* @Groups({"organization:collection:get"})
* @ORM\Column(type="string", length=150, nullable=true)
*/
public ?string $disambiguating_description = null;
/**
* @ApiProperty(iri="https://schema.org/addressCountry")
* @ORM\Column(type="string", length=2, nullable=true)
*/
public ?string $country = null;
/**
* @ApiProperty(iri="https://schema.org/addressRegion")
* @ORM\Column(type="string", nullable=true)
*/
public ?string $region = null;
/**
* @ApiProperty(iri="https://schema.org/streetAddress")
* @ORM\Column(type="string", nullable=true)
*/
public ?string $street = null;
/**
* @ApiProperty(iri="https://schema.org/telephone")
* @ORM\Column(type="string", nullable=true)
*/
public ?string $telephone = null;
/**
* @ApiProperty(iri="https://schema.org/email")
* @ORM\Column(type="string", nullable=true)
*/
public ?string $email = null;
/**
* @ApiProperty(iri="https://schema.org/contentUrl")
* @Groups({"logo_read"})
*/
public ?string $logoContentUrl = null;
/**
* @var File|null
*
* @Assert\NotNull(groups={"logo_create"})
* @Vich\UploadableField(mapping="logo", fileNameProperty="logoPath")
*/
public ?File $logoFile = null;
public function __construct()
{
$this->status = OrganizationStatus::DRAFT()->getValue();
}
public function getId(): ?Uuid
{
return $this->id ?? null;
}
public function setId(Uuid $id)
{
$this->id = $id;
}
}
final class CreateOrganizationLogoAction extends AbstractController
{
const OPERATION_NAME = 'post_logo';
const OPERATION_PATH = '/places/{id}/logo';
private OrganizationPgRepository $repository;
public function __construct(OrganizationPgRepository $repository)
{
$this->repository = $repository;
}
/**
* @param Request $request
*
* @return EntityOrganization
*/
public function __invoke(Request $request): EntityOrganization
{
$uploadedFile = $request->files->get('logoFile');
if (!$uploadedFile) {
throw new BadRequestHttpException('"file" is required');
}
$organization = $this->repository->find(Uuid::fromString($request->attributes->get('id')));
$organization->logoFile = $uploadedFile;
return $organization;
}
}
我正在发送请求:
curl -X POST "http://localhost:8081/api/places/0dc43a86-6402-4a45-8392-19d5e398a7ab/logo" -H "accept: application/ld+json" -H "Content-Type: multipart/form-data" -F "logoFile=@test.png;type=image/png"
...并得到响应:
{
"@context": "/api/contexts/Place",
"@id": "/api/places/0dc43a86-6402-4a45-8392-19d5e398a7ab",
"@type": "https://schema.org/Organization",
"slug": "consequatur-aut-optio-corrupti-quod-sit-libero-aspernatur",
"status": 0,
"title": "Block LLC",
"logoPath": "a268cde1-d93e-4d48-9f0d-177b4f89f1f8.png",
"description": "Nisi sint ducimus consequatur dicta sint maxime. Et soluta facere in quisquam quia. Tempore quae non qui dignissimos optio rem cum illum. Eum similique vitae autem aut. Reiciendis nesciunt rerum libero in consequuntur excepturi repellendus unde. Tempore ea perferendis sunt quibusdam autem est. Similique qui illum necessitatibus velit dolores. Voluptas sapiente excepturi ad assumenda exercitationem est. Nesciunt sint sint fugiat quis blanditiis. Rerum vel sint temporibus nobis fugiat nostrum aut. Voluptatibus temporibus magnam cumque asperiores. Adipisci qui perferendis mollitia tempore accusantium aut. Possimus numquam asperiores repellendus non facilis.",
"disambiguating_description": "Et libero temporibus ut impedit esse ipsum quam.",
"country": "RU",
"region": "Idaho",
"street": "15544 Delbert Underpass",
"telephone": "+78891211558",
"email": "lhintz@corwin.com",
"pictures": [],
"social_profiles": [],
"logoContentUrl": "/logo/a268cde1-d93e-4d48-9f0d-177b4f89f1f8.png",
"logoFile": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD//gA7Q1JFQVRPUjog
...
...
... TgjNWnJ7YWPrMCWGxWbi57Tj58TfPQL1Hi54DRFD/FkuLcuXBKFB3TFLcuaUvpqKuYUJaLL/yV/R/+kf/Z",
"id": "0dc43a86-6402-4a45-8392-19d5e398a7ab"
}
如您所见,一切正常。找到了适当的组织。甚至 logoFile 字段都充满了上传的图片。但上传的文件没有移动到目的地。并且 logoPath 包含旧的 logo 文件名。
正如我所说,没有错误。 请帮我弄清楚在哪里挖掘。
【问题讨论】:
-
您说:“上传的文件没有移动到目的地”。但老实说,我真的没有看到任何代码应该发生这种移动。我怀疑它会在
__invoke函数中。在那里你得到图像,但你不移动它。您将其分配给organisation,但您不保存更新后的组织。这样您的返回数据看起来是正确的,但任何新请求都将使用旧设置 -
@MaartenVeerman 但在文档中没有提到手动移动或持久化。不在 Api Platform 文档中,也不在 Vich Uploader 文档中。我认为这项工作是由捆绑自己完成的。当我尝试重复这些文档中的示例时,一切正常。但我不会手动移动或坚持任何东西。
-
@avkryukov 我的解决方案是否解决了您的问题?我在我从事的项目中已经有很多次了,所以我很确定就是这样。但如果不是这样会更有趣。
-
@PhilipWeinke 实际上我已经拒绝将 VichUploader Bundle 与 ApiPlatform 结合使用。但!您的解决方案看起来很合理!我绝对需要分叉我的项目来测试它。我注意到我的代码没有保留更新的组织。但是有了新记录,它就可以正常工作了。所以你 100% 是正确的。
标签: php api-platform.com symfony5 vichuploaderbundle