【问题标题】:Gaufrette (with AWS) & Symfony 4 - Read a pictureGaufrette(使用 AWS)和 Symfony 4 - 阅读图片
【发布时间】:2020-07-07 04:45:24
【问题描述】:

下午好,

我尝试显示来自 AWS S3 存储的图像。我使用在 AWS S3 存储中上传文件时可以使用的 gaufrette 文件配置。

薄纱配置:

knp_gaufrette:
    adapters:
        images:
            aws_s3:
                service_id: "infra.aws_s3.client"
                bucket_name: "%amazon_s3.bucket_name%"
                detect_content_type: true
                options:
                    directory: "%amazon_s3.directories.images%"
                    acl: public-read
        documents:
            aws_s3:
                service_id: "infra.aws_s3.client"
                bucket_name: "%amazon_s3.bucket_name%"
                detect_content_type: true
                options:
                    directory: "%amazon_s3.directories.documents%"
                    acl: public-read
        imports:
            aws_s3:
                service_id: "infra.aws_s3.client"
                bucket_name: "%amazon_s3.bucket_name%"
                detect_content_type: true
                options:
                    directory: "%amazon_s3.directories.imports%"
                    acl: public-read
    filesystems:
        images:
            adapter: images
            alias: images_filesystem
        documents:
            adapter: documents
            alias: documents_filesystem
        imports:
            adapter: imports
            alias: imports_filesystem

控制器代码:

<?php

namespace App\Application\Controller;

use App\Application\Controller\Rest\RestController;
use App\Domain\Entity\BuildingMedia;
use App\Domain\Entity\PropertyPicture;
use App\Infrastructure\Command\Command\CommandBus;
use App\Infrastructure\Repository\BuildingMediaRepository;
use App\Infrastructure\Repository\PropertyPictureRepository;
use Gaufrette\Filesystem;
use Gaufrette\StreamWrapper;
use JMS\Serializer\SerializerInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Swagger\Annotations as SWG;
use Nelmio\ApiDocBundle\Annotation\Operation;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

class MediaController extends RestController
{
    /**
     * @var PropertyPictureRepository
     */
    private $propertyPictureRepository;

    /**
     * @var BuildingMediaRepository
     */
    private $buildingMediaRepository;

    /**
     * @var Filesystem
     */
    private $awsS3;

    /**
     * MediaController constructor.
     *
     * @param PropertyPictureRepository $propertyPictureRepository
     * @param BuildingMediaRepository   $buildingMediaRepository
     * @param Filesystem                $awsS3
     * @param SerializerInterface       $serializer
     * @param CommandBus                $commandBus
     */
    public function __construct(
        PropertyPictureRepository $propertyPictureRepository,
        BuildingMediaRepository $buildingMediaRepository,
        Filesystem $awsS3,
        SerializerInterface $serializer,
        CommandBus $commandBus
    ) {
        $this->propertyPictureRepository = $propertyPictureRepository;
        $this->buildingMediaRepository = $buildingMediaRepository;
        $this->awsS3 = $awsS3;

        parent::__construct($serializer, $commandBus);
    }

    /**
     * @Operation(
     *     tags={"Media"},
     *     summary="Read a property's picture.",
     *     @SWG\Response(
     *         response="200",
     *         description="OK"
     *     ),
     *     @SWG\Response(
     *         response="400",
     *         description="Bad request"
     *     ),
     *     @SWG\Response(
     *         response="401",
     *         description="Unauthorized"
     *     ),
     *     @SWG\Response(
     *         response="403",
     *         description="Access denied"
     *     ),
     *     @SWG\Response(
     *         response="404",
     *         description="Entity not found"
     *     ),
     *     @SWG\Response(
     *         response="500",
     *         description="Internal server error"
     *     )
     * )
     *
     * @ParamConverter("propertyPicture", converter="property_picture")
     *
     * @param PropertyPicture $propertyPicture
     *
     * @return BinaryFileResponse
     */
    public function propertyPictureReadAction(PropertyPicture $propertyPicture): BinaryFileResponse
    {
        $adapter = $this->awsS3->getAdapter();

        $filePath = $adapter->read(
            'group'.DIRECTORY_SEPARATOR.
            $this->getUser()->getGroupId().DIRECTORY_SEPARATOR.
            'property'.DIRECTORY_SEPARATOR.
            $propertyPicture->getProperty()->getIdValue().DIRECTORY_SEPARATOR.
            $propertyPicture->getFilename()
        );

        $response = new BinaryFileResponse($filepath);
        $response->headers->set('Content-Type', 'image/jpeg');
        $response->setContentDisposition(
            ResponseHeaderBag::DISPOSITION_INLINE,
            $propertyPicture->getFilename()
        );

        return $response;
    }
}

如果我尝试使用 $propertyPicture 中的 getLink()(该方法返回保存在数据库中的文件 URL),BinaryFileResponse 找不到来自给定 URL 的文件。

我需要从 Gaufrette 获得文件 URL 以在 API 响应中显示文件。

【问题讨论】:

    标签: php amazon-web-services symfony amazon-s3 gaufrette


    【解决方案1】:

    在尝试了许多可能的解决方案后,我找到了这个用于图片的解决方案(即使您在 AWS S3 中使用私有存储桶,它也能正常工作):

    <?php
    
    namespace App\Application\Controller;
    
    use App\Application\Controller\Rest\RestController;
    use App\Domain\Entity\BuildingMedia;
    use App\Domain\Entity\PropertyPicture;
    use App\Infrastructure\Command\Command\CommandBus;
    use App\Infrastructure\Repository\BuildingMediaRepository;
    use App\Infrastructure\Repository\PropertyPictureRepository;
    use Gaufrette\Filesystem;
    use JMS\Serializer\SerializerInterface;
    use Symfony\Component\HttpFoundation\Response;
    use Swagger\Annotations as SWG;
    use Nelmio\ApiDocBundle\Annotation\Operation;
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
    use Symfony\Component\HttpKernel\Exception\HttpException;
    
    class MediaController extends RestController
    {
        /**
         * @var PropertyPictureRepository
         */
        private $propertyPictureRepository;
    
        /**
         * @var BuildingMediaRepository
         */
        private $buildingMediaRepository;
    
        /**
         * @var Filesystem
         */
        private $awsS3;
    
        /**
         * MediaController constructor.
         *
         * @param PropertyPictureRepository $propertyPictureRepository
         * @param BuildingMediaRepository   $buildingMediaRepository
         * @param Filesystem                $awsS3
         * @param SerializerInterface       $serializer
         * @param CommandBus                $commandBus
         */
        public function __construct(
            PropertyPictureRepository $propertyPictureRepository,
            BuildingMediaRepository $buildingMediaRepository,
            Filesystem $awsS3,
            SerializerInterface $serializer,
            CommandBus $commandBus
        ) {
            $this->propertyPictureRepository = $propertyPictureRepository;
            $this->buildingMediaRepository = $buildingMediaRepository;
            $this->awsS3 = $awsS3;
    
            parent::__construct($serializer, $commandBus);
        }
    
        /**
         * @Operation(
         *     tags={"Media"},
         *     summary="Read a property's picture.",
         *     @SWG\Response(
         *         response="200",
         *         description="OK"
         *     ),
         *     @SWG\Response(
         *         response="400",
         *         description="Bad request"
         *     ),
         *     @SWG\Response(
         *         response="401",
         *         description="Unauthorized"
         *     ),
         *     @SWG\Response(
         *         response="403",
         *         description="Access denied"
         *     ),
         *     @SWG\Response(
         *         response="404",
         *         description="Entity not found"
         *     ),
         *     @SWG\Response(
         *         response="500",
         *         description="Internal server error"
         *     )
         * )
         *
         * @ParamConverter("propertyPicture", converter="property_picture")
         *
         * @param PropertyPicture $propertyPicture
         *
         * @return Response
         */
        public function propertyPictureReadAction(PropertyPicture $propertyPicture): Response
        {
            $adapter = $this->awsS3->getAdapter();
    
            $content = $adapter->read(
                'group'.DIRECTORY_SEPARATOR.
                $this->getUser()->getGroupId().DIRECTORY_SEPARATOR.
                'property'.DIRECTORY_SEPARATOR.
                $propertyPicture->getProperty()->getIdValue().DIRECTORY_SEPARATOR.
                $propertyPicture->getFilename()
            );
    
            return new Response($content, 200, array(
                    'Content-Type' => 'image/jpeg'
            ));
        }
    }
    

    Gaufrette 中的 read() 方法返回文件内容,而不是真实路径。因此,我只需将返回值从 BinaryFileResponse 更改为 Response 并手动设置 Content-Type

    下一次升级,如果你有相同的处理是在文件保存时在数据库中设置类型 MIME,并在你需要显示它时返回它,就像你的 API 中的类似路由一样。

    【讨论】:

      猜你喜欢
      • 2016-06-10
      • 2020-01-05
      • 2019-01-06
      • 2020-01-18
      • 2016-10-01
      • 2015-04-23
      • 1970-01-01
      • 2020-06-12
      • 1970-01-01
      相关资源
      最近更新 更多