paneedesign/storage-bundle

一个提供用于处理本地或S3上媒体存储的工具的Symfony扩展包。

v6.0.3 2021-04-12 07:19 UTC

README

Latest Stable Version Total Downloads Latest Unstable Version License

一个提供用于处理本地或S3上媒体存储的工具的Symfony扩展包。

安装

步骤 1:下载扩展包

打开命令行,进入项目目录并执行以下命令以下载此扩展包的最新稳定版本

$ composer require "paneedesign/storage-bundle"

此命令需要您全局安装Composer,如Composer文档的安装章节中所述。

步骤 2:启用扩展包

然后,将扩展包添加到项目app/AppKernel.php文件中注册的扩展包列表中,以启用扩展包

<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            // ...

            new \Fresh\DoctrineEnumBundle\FreshDoctrineEnumBundle(),
            new \Liip\ImagineBundle\LiipImagineBundle(),
            new \Knp\Bundle\GaufretteBundle\KnpGaufretteBundle(),
            new \PaneeDesign\DiscriminatorMapBundle\PedDiscriminatorMapBundle(),
            new \PaneeDesign\StorageBundle\PedStorageBundle(),
        );

        // ...
    }

    // ...
}

步骤 3:配置

添加到.env

###> paneedesign/storage-bundle ###
STORAGE_ADAPTER=local
STORAGE_DIRECTORY=uploads
STORAGE_THUMBS_PREFIX=thumbs
STORAGE_LOCAL_ENDPOINT=/uploads
###< paneedesign/storage-bundle ###

###> paneedesign/storage-bundle ###
STORAGE_ADAPTER=amazon_s3
STORAGE_DIRECTORY=uploads
STORAGE_THUMBS_PREFIX=thumbs
STORAGE_AMAZON_S3_KEY=key
STORAGE_AMAZON_S3_SECRET=secret
STORAGE_AMAZON_S3_REGION=eu-west-2
STORAGE_AMAZON_S3_ENDPOINT=https://s3.amazonaws.com
STORAGE_AMAZON_S3_BUCKET_NAME=ped-local
STORAGE_AMAZON_S3_EXPIRE_AT="+1 hour"
###< paneedesign/storage-bundle ###

将以下文件复制到config/packeges下:

  • config/packeges/ped_storage.yaml

并在config/routes下:

  • config/routes/ped_storage.yaml

设置到config/packages/doctrine.yaml

//...

doctrine:
    dbal:
        types:
            enum_media_type: PaneeDesign\StorageBundle\DBAL\EnumMediaType
            enum_file_type: PaneeDesign\StorageBundle\DBAL\EnumFileType

和到config/packages/ped_discriminator_map.yaml

//...

ped_discriminator_map:
    maps:
        media:
            entity: PaneeDesign\StorageBundle\Entity\Media
            children:
                app_media: AppBundle\Entity\Media
        ...

步骤 4:使用

您可以使用这些代码片段存储图片或文档,并检索资源的完整URL

<?php

declare(strict_types=1);

namespace App\Handler;

use App\Entity\Media;
use Gaufrette\Extras\Resolvable\UnresolvableObjectException;
use PaneeDesign\StorageBundle\DBAL\EnumFileType;
use PaneeDesign\StorageBundle\DBAL\EnumMediaType;
use PaneeDesign\StorageBundle\Entity\Media as PedMedia;
use PaneeDesign\StorageBundle\Handler\MediaHandler;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Routing\RouterInterface;

class StorageHandler
{
    /**
     * @var RouterInterface
     */
    protected $router;
    /**
     * @var MediaHandler
     */
    private $mediaHandler;

    /**
     * MediaManager constructor.
     *
     * @param MediaHandler    $mediaHandler
     * @param RouterInterface $router
     */
    public function __construct(MediaHandler $mediaHandler, RouterInterface $router)
    {
        $this->mediaHandler = $mediaHandler;
        $this->router = $router;
    }

    /**
     * @param PedMedia    $media
     * @param string|null $filter
     *
     * @return string
     */
    public function generateAbsoluteUri(PedMedia $media, ?string $filter = null)
    {
        $url = '';

        try {
            if (null !== $filter) {
                if ($media->hasFilter($filter)) {
                    $url = $media->getUrl($filter);
                } else {
                    $url = $this->router->generate('ped_storage_image', [
                        'key' => $media->getKey(),
                        'filter' => $filter,
                    ]);
                }
            } else {
                $url = $this->mediaHandler->getFullUrl($media->getFullKey());
            }
        } catch (UnresolvableObjectException $e) {
        } catch (\Exception $e) {
        }

        return $url ?: '';
    }

    /**
     * @param int           $entityId
     * @param string        $type
     * @param UploadedFile  $media
     * @param PedMedia|null $image
     * @param string|null   $mediaType
     *
     * @throws \Exception
     *
     * @return Media
     */
    public function storeImage(
        int $entityId,
        string $type,
        UploadedFile $media,
        ?PedMedia $image = null,
        ?string $mediaType = EnumMediaType::PROFILE
    ): Media {
        $hasPublicAccess = false;
        $allowedMimeTypes = [
            'image/jpeg',
            'image/png',
            'image/gif',
        ];

        $uploader = $this->getUploader($entityId, $type, EnumFileType::IMAGE, $hasPublicAccess, $allowedMimeTypes);

        if (null === $image) {
            $image = new Media();
            $image->setType($mediaType);
        } else {
            $image->clearFilters();
            $uploader->remove($image);
        }

        $uploader->save($media);

        $image = new Media();
        $image->setKey($uploader->getKey());
        $image->setPath($uploader->getFullKey(''));
        $image->setFileType($uploader->getFileType());
        $image->setSize($media->getSize());
        $image->setIsPublic($uploader->getHasPublicAccess());

        return $image;
    }

    /**
     * @param int           $entityId
     * @param string        $type
     * @param UploadedFile  $media
     * @param PedMedia|null $document
     * @param string|null   $mediaType
     *
     * @throws \Exception
     *
     * @return Media
     */
    public function storeDocument(
        int $entityId,
        string $type,
        UploadedFile $media,
        ?PedMedia $document = null,
        ?string $mediaType = EnumMediaType::DOCUMENT
    ): Media {
        $hasPublicAccess = true;
        $allowedMimeTypes = [
            'image/jpeg',
            'image/png',
            'image/gif',
            'application/pdf',
        ];

        $uploader = $this->getUploader($entityId, $type, EnumFileType::DOCUMENT, $hasPublicAccess, $allowedMimeTypes);

        if (null === $document) {
            $document = new Media();
            $document->setType($mediaType);
        } else {
            $document->clearFilters();
            $uploader->remove($document);
        }

        $uploader->save($media);

        $document = new Media();
        $document->setKey($uploader->getKey());
        $document->setPath($uploader->getFullKey(''));
        $document->setFileType($uploader->getFileType());
        $document->setSize($media->getSize());
        $document->setIsPublic($uploader->getHasPublicAccess());

        return $document;
    }

    /**
     * @param int    $entityId
     * @param string $type
     * @param string $fileType
     * @param array  $allowedMimeTypes
     * @param bool   $hasPublicAccess
     *
     * @return MediaHandler
     */
    private function getUploader(
        int $entityId,
        string $type,
        string $fileType,
        bool $hasPublicAccess,
        array $allowedMimeTypes = []
    ): MediaHandler {
        /* @var MediaHandler $uploader */
        $uploader = $this->mediaHandler
            ->setId($entityId)
            ->setType($type)
            ->setFileType($fileType)
            ->setAllowedMimeTypes($allowedMimeTypes)
            ->setHasPublicAccess($hasPublicAccess);

        return $uploader;
    }
}

附加功能

缩放

必需

  • 过滤器

config/packages/liip_imagine.yaml中定义过滤器如下

liip_imagine:
    #filters
    filter_sets:
        # 1x1
        icon_1-1:
            quality: 75
            filters:
                relative_resize:
                    heighten: 40
                thumbnail:
                    size: [40, 40]
                    mode: outbound
                    allow_upscale: true
        small_1-1:
            quality: 75
            filters:
                relative_resize:
                    heighten: 400
                thumbnail:
                    size: [400, 400]
                    mode: outbound
                    allow_upscale: true
        medium_1-1:
            quality: 85
            filters:
                relative_resize:
                    heighten: 800
                thumbnail:
                    size: [800, 800]
                    mode: outbound
                    allow_upscale: true
        large_1-1:
            quality: 90
            filters:
                relative_resize:
                    heighten: 1200
                thumbnail:
                    size: [1200, 1200]
                    mode: outbound
                    allow_upscale: true
        xlarge_1-1:
            quality: 95
            filters:
                relative_resize:
                    heighten: 1600
                thumbnail:
                    size: [1600, 1600]
                    mode: outbound
                    allow_upscale: true

因此,当您调用此URL http://example.com/image/5dc350316d2ee.jpeg?filter=icon_1-1 时,您将得到一个缩放至40x40像素的方形图片

裁剪

必需

  • 过滤器
  • 起始-x
  • 起始-y
  • 宽度
  • 高度

当您调用此URL http://example.com/image/5dc350316d2ee.jpeg?filter=crop_medium_1-1&start-x=20&start-y=50&width=800&height=800 时,将medium_1-1的缩放选项与裁剪信息结合

因此,您将得到从原点[20,50][820,850](宽度和高度均为800px)的裁剪,并缩放至800x800px

旋转

必需

  • 过滤器
  • 角度

当您调用此URL http://example.com/image/5dc350316d2ee.jpeg?filter=rotate_medium_1-1&angle=90 时,将medium_1-1的缩放选项与旋转角度结合

因此,原始图片旋转90°,并缩放至800x800px

作者

👤 Fabiano Roberto fabiano.roberto@ped.technology

👤 Luigi Cardamone luigi.cardamone@ped.technology

🤝 贡献

欢迎贡献、问题和功能请求!
请随时查看问题页面

展示您的支持

如果此项目对您有所帮助,请给它一个⭐️!

本README由readme-md-generator生成,用❤️。