亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

處理文件上傳的 API 平臺

處理文件上傳的 API 平臺

PHP
RISEBY 2023-08-06 14:55:22
我正在嘗試使用 Api Platform 和 Vich Uploader Bundle 上傳文件。當我發送帶有 multipart/form-data 和要附加圖像文件的實體 ID 的 POST 請求時,我的實體收到 200 響應。但上傳的文件不會上傳到目標目錄,并且生成的文件名不會保留。沒有錯誤,沒有任何線索,沒有想法。這是我的代碼://vich uploader mappingsvich_uploader:    db_driver: orm    mappings:        logo:            uri_prefix: /logo            upload_destination: '%kernel.project_dir%/public/images/logo/'            namer: App\Infrastructure\Naming\LogoNamerfinal 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 "[email protected];type=image/png"正如你所看到的,一切都很好。找到了適當的組織。甚至 logoFile 字段也被上傳的圖片填滿。但上傳的文件并未移動到目的地。并且 logoPath 包含舊徽標文件名。正如我所說,沒有錯誤。請幫我弄清楚在哪里挖掘。
查看完整描述

2 回答

?
達令說

TA貢獻1821條經驗 獲得超6個贊

VichUploaderBundle 使用 prePersist 和 preUpdate 掛鉤在學說事件監聽器中進行上傳處理。你的情況的問題是,從學說的角度來看,持久性財產沒有改變。由于沒有更改,因此不會調用上傳偵聽器。


一個簡單的解決方法是在上傳文件時始終更改持久屬性。我向您的實體添加了將和所需的更改保持在一起updatedAt的方法。updateLogologoFileupdatedAt


final class Organization

{

    (...)


    /**

     * @ApiProperty(iri="http://schema.org/logo")

     * @Groups({"organization:collection:get", "logo:post"})

     * @ORM\Column(nullable=true)

     */

    public ?string $logoPath = null;


    /**

     * @ORM\Column(type="datetime")

     */

    private ?DateTime $updatedAt = null;


    /**

     * @var File|null

     *

     * @Assert\NotNull(groups={"logo_create"})

     * @Vich\UploadableField(mapping="logo", fileNameProperty="logoPath")

     */

    private ?File $logoFile = null;

    

    (...)


    public function updateLogo(File $logo): void

    {

       $this->logoFile  = $logo;

       $this->updatedAt = new DateTime();

    }

}

final class CreateOrganizationLogoAction extends AbstractController

{

    (...)


    /**

     * @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->updateLogo($uploadedFile);


        return $organization;

    }

}


查看完整回答
反對 回復 2023-08-06
?
犯罪嫌疑人X

TA貢獻2080條經驗 獲得超4個贊

我目前正在開發一個允許用戶上傳媒體文件的項目。


我已經丟棄了 Vich 包。Api平臺是面向application/ld+json的。


相反,我讓用戶提供一個 base64 編碼的內容文件(即僅包含可讀字符的字符串表示形式)。


我得到的唯一對應結果是,在 http 傳輸期間文件大小增加了約 30%。老實說,沒關系。


我建議你做類似下面代碼的事情。


OrganizationController --use-->組織1 <>---> 0..1 ImageObject


徽標(請注意$encodingFormat屬性上的斷言):


<?php


declare(strict_types=1);


namespace App\Entity;


use ApiPlatform\Core\Annotation\ApiProperty;

use ApiPlatform\Core\Annotation\ApiResource;

use Doctrine\ORM\Mapping as ORM;

use Symfony\Component\Serializer\Annotation\Groups;

use Symfony\Component\Validator\Constraints as Assert;


/**

 * An image file.

 *

 * @see http://schema.org/ImageObject Documentation on Schema.org

 *

 * @ORM\Entity

 * @ApiResource(

 *     iri="http://schema.org/ImageObject",

 *     normalizationContext={"groups" = {"imageobject:get"}}

 *     collectionOperations={"get"},

 *     itemOperations={"get"}

 * )

 */

class ImageObject

{

    /**

     * @var int|null

     *

     * @ORM\Id

     * @ORM\GeneratedValue(strategy="AUTO")

     * @ORM\Column(type="integer")

     * @Groups({"imageobject:get"})

     */

    private $id;


    /**

     * @var string|null the name of the item

     *

     * @ORM\Column(type="text", nullable=true)

     * @ApiProperty(iri="http://schema.org/name")

     * @Groups({"imageobject:get"})

     */

    private $name;


    /**

     * @var string|null actual bytes of the media object, for example the image file or video file

     *

     * @ORM\Column(type="text", nullable=true)

     * @ApiProperty(iri="http://schema.org/contentUrl")

     * @Groups({"imageobject:get"})

     */

    private $contentUrl;


    /**

     * @var string|null mp3, mpeg4, etc

     *

     * @Assert\Regex("#^image/.*$#", message="This is not an image, this is a {{ value }} file.")

     * @ORM\Column(type="text", nullable=true)

     * @ApiProperty(iri="http://schema.org/encodingFormat")

     * @Groups({"imageobject:get"})

     */

    private $encodingFormat;

    

    // getters and setters, nothing specific here

您剝離的Organization類,聲明OrganizationController:


<?php


namespace App\Entity;


use ApiPlatform\Core\Annotation\ApiResource;

use App\Repository\OrganizationRepository;

use Doctrine\ORM\Mapping as ORM;

use Symfony\Component\Serializer\Annotation\Groups;

use Symfony\Component\Validator\Constraints as Assert;

use App\Controller\OrganizationController;


/**

 * @ApiResource(

 *     normalizationContext={

            "groups" = {"organization:get"}

 *     },

 *     denormalizationContext={

            "groups" = {"organization:post"}

 *     },

 *     collectionOperations={

            "get",

 *          "post" = {

 *              "controller" = OrganizationController::class

 *          }

 *     }

 * )

 * @ORM\Entity(repositoryClass=OrganizationRepository::class)

 */

class Organization

{

    /**

     * @ORM\Id()

     * @ORM\GeneratedValue()

     * @ORM\Column(type="integer")

     * @Groups({"organization:get"})

     */

    private $id;


    /**

     * @var string

     * @ORM\Column(type="string", length=100, unique=true)

     * @Groups({"organization:get", "organization:post"})

     */

    private $slug;


    /**

     * @var null|ImageObject

     * @Assert\Valid()

     * @ORM\OneToOne(targetEntity=ImageObject::class, cascade={"persist", "remove"})

     * @Groups({"organization:get"})

     */

    private $logo;


    /**

     * @var string the logo BLOB, base64-encoded, without line separators.

     * @Groups({"organization:post"})

     */

    private $b64LogoContent;


    // getters and setters, nothing specific here...


}

請注意$logo和$b64LogoContent屬性的序列化組。


然后是控制器(動作類),以解碼、分配和寫入標識內容。


<?php



namespace App\Controller;


use App\Entity\ImageObject;

use App\Entity\Organization;

use finfo;


/**

 * Handle the base64-encoded logo content.

 */

class OrganizationController

{

    public function __invoke(Organization $data)

    {

        $b64LogoContent = $data->getB64LogoContent();

        if (! empty($b64LogoContent)) {

            $logo = $this->buildAndWriteLogo($b64LogoContent);

            $data->setLogo($logo);

        }

        return $data;

    }


    private function buildAndWriteLogo(string $b64LogoContent): ImageObject

    {

        $logo = new ImageObject();

        $content = str_replace("\n", "", base64_decode($b64LogoContent));

        $mimeType = (new finfo())->buffer($content, FILEINFO_MIME_TYPE);

        $autoGeneratedId = $this->createFileName($content, $mimeType); // Or anything to generate an ID, like md5sum

        $logo->setName($autoGeneratedId);

        $logo->setContentUrl("/public/images/logo/$autoGeneratedId");

        $logo->setEncodingFormat($mimeType);

        // check the directory permissions!

        // writing the file should be done after data validation

        file_put_contents("images/logo/$autoGeneratedId", $content);

        return $logo;

    }


    private function createFileName(string $content, string $mimeType): string

    {

        if (strpos($mimeType, "image/") === 0) {

            $extension = explode('/', $mimeType)[1];

        } else {

            $extension = "txt";

        }

        return time() . ".$extension";

    }

}

它檢查提供的徽標是否是帶有ImageObject 類的@Assert注釋(encodingFormat、寬度、高度等)的“小圖像”,它們由Organization::$logo屬性的@Assert\Valid注釋觸發。


這樣,您可以通過發送單個HTTP POST /organizations請求來創建帶有其徽標的組織。


查看完整回答
反對 回復 2023-08-06
  • 2 回答
  • 0 關注
  • 129 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號