使用flysystem和liip_imagine配置aws_s3



我的symfony 5.4项目使用aws_s3+flysystem+liip_imagine。

在aws_s3中,我有一个PRIVATE bucket:"myBucket";包含3个子文件夹:

  • 文档
  • 照片
  • 媒体

和IAM许可

    "Effect": "Allow",
        "Action": [
            "s3:ListBucket",
            "s3:GetObject",
            "s3:DeleteObject",
            "s3:GetObjectAcl",
            "s3:PutObjectAcl",
            "s3:PutObject"
        ],
        "Resource": [
            "arn:aws:s3:::myBucket",
            "arn:aws:s3:::mybucket/*"
        ]

我的设置:请参阅:https://github.com/liip/LiipImagineBundle/issues/823

Service.yaml

...
parameters:
    uploads_base_url: '%env(AWS_S3_UPLOAD_BASE_URL)%'   
services : 
    AwsS3S3Client:
        arguments:
            -
                version: '2006-03-01'
                region: '%env(AWS_S3_ACCESS_REGION)%' 
                credentials:
                    key: '%env(AWS_S3_ACCESS_ID)%'
                    secret: '%env(AWS_S3_ACCESS_SECRET)%'

oneup_flysystem.yaml

...
adapters:
    aws_s3_adapter:                    
        awss3v3:
            client : AwsS3S3Client
            bucket: '%env(AWS_S3_BUCKET_NAME)%'
            options:
                ACL: bucket-owner-full-control
filesystems:
    aws_s3_system:
        adapter: aws_s3_adapter

lipp_imagine.yaml

# https://symfony.com/bundles/LiipImagineBundle/current/cache-resolver/aws_s3.html
# I do not understand everything
...
    driver: "gd"
    loaders:
        aws_s3_loader:  
            flysystem:
                filesystem_service: oneup_flysystem.aws_s3_system_filesystem
    data_loader: aws_s3_loader
    resolvers:
        aws_s3_resolver:
            flysystem:
                filesystem_service: oneup_flysystem.aws_s3_system_filesystem
                root_url: '%uploads_base_url%'
                cache_prefix: media/cache
     
    cache: aws_s3_resolver 
    filter_sets:
        squared_thumbnail_small:
            quality: 70
            filters:
                thumbnail:
                    size:          [50, 50]
                    mode:          outbound

树枝

# call twig_function assetPresigned
<a href="{{ assetPresigned('photos', player.photoFilename) }}" target="_blank">
    <img src="{{ assetPresigned('photos', player.photoFilename ) | imagine_filter('squared_thumbnail_small') }}" alt="photo">
</a>

FileUploadService.php


    public function assetPresigned(string $folder, string $filename): string
    {
        $command = $this->s3Client->getCommand('GetObject', [
            'Bucket' => $this->awsS3BucketName,
            'Key'    => $folder.'/'.$filename,
        ]);
        // RETURN PRESIGNED URL
        $urlPresigned = $this->s3Client->createPresignedRequest($command, '+5 minutes');
        return ((string) $urlPresigned->getUri());
    }

第1位:我的问题是;squared_thumbnail_small";过滤器重写url,删除预先签名的

结果在树枝:

  • href:图像显示在单击时,因为url是预签名的
  • img:url失去签名,因此不显示

nb:它是liip_imagine via"imagine_filter('squared_tumbnail_small(,它在mybucket/media中创建缩略图。在这个阶段,缩略图还没有出现在mybucket/media中,因为它还没有显示

问题:如何正确配置我的代码,使筛选器不会删除预签名?

这是我尝试过的

FileUploadService.php-

namespace AppService;
...
 public function assetPresigned(string $folder, string $filename): string
    {
       # call ImagineFilterService.php 
       $this->imagineFilter->filter($folder.'/'.$filename);
        # ...
        $command....
    }

ImagineFilterService.php

namespace AppService;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationRedirectResponse;
use LiipImagineBundleImagineCacheCacheManager;
use LiipImagineBundleImagineDataDataManager;
use LiipImagineBundleImagineFilterFilterManager;
use AppServiceFileUploadService;
# https://symfony.com/bundles/LiipImagineBundle/current/filters.html#dynamic-filters
# I tried to create a filter dynamically based on this documentation
Class ImagineFilterService
public function filter($path) 
{
    $filter = 'squared_thumbnail_small';                 
    # if photo is not stored in myBucket/media then you save it by applying the filter?
    if (!$this->cacheManager->isStored($path, $filter)) {
        $binary = $this->dataManager->find($filter, $path);
        $filteredBinary = $this->filterManager->applyFilter($binary, $filter);
        # In this method, I pass in parameter the resolver
        $this->cacheManager->store($filteredBinary, $path, $filter, 'aws_s3_resolver');           
    }
    // ERROR 403!!!
    return $this->cacheManager->resolve($path, $filter);
}

我现在恢复已经存储在myBucket/media(ok(中的缩略图

但在myBucket/media中保存新缩略图时,我出现了403错误。

AWS HTTP错误:客户端错误:PUT resulted in a 403 Forbidden`响应:拒绝访问

所以我失去了证书。

这对我来说很复杂,准确的答案(参见一段代码(会对我有很大帮助。我不知道我错在哪里了。我已经被卡住好几天了

谢谢你的帮助。

嘿,我找到了一个保留签名url的解决方案。我不知道我们是否可以做得更简单,但它有效。

包裹

  • "liip/想象捆绑包":"2.10">
  • "联盟/飞行系统-aws-s3-v3":"3.13">
  • "联盟/飞行系统捆绑包":"3.1〃
  • "oneup/flysystem束":"4.6〃

S3Client的示例

//service.yaml
AwsS3S3Client:
    arguments:
        -   endpoint: '%env(IONOS_S3_ENDPOINT)%'
            version: '%env(IONOS_S3_VERSION)%'
            region: '%env(IONOS_S3_REGION)%'
            credentials:
                key: '%env(IONOS_S3_ACCESS_ID)%'
                secret: '%env(IONOS_S3_ACCESS_SECRET)%'

我有一个端点论点,因为我使用ionos作为s3。

配置您的适配器及其文件系统,以便在其中加载您的映像

    //oneup_flysystem.yaml
oneup_flysystem:
    adapters:
        user_adapter:
            awss3v3:
                client: AwsS3S3Client
                bucket: '%env(IONOS_S3_BUCKET_NAME)%'
                prefix: "users"
        user_thumbnail_adapter:
            awss3v3:
                client: AwsS3S3Client
                bucket: '%env(IONOS_S3_BUCKET_NAME)%'
                prefix: "cache/user_thumbnail"
        user_medium_adapter:
            awss3v3:
                client: AwsS3S3Client
                bucket: '%env(IONOS_S3_BUCKET_NAME)%'
                prefix: "cache/user_medium"
    filesystems:
        user:
            adapter: user_adapter
            mount: user
        userThumbnail:
            adapter: user_thumbnail_adapter
            mount: userThumbnail
        userMedium:
            adapter: user_medium_adapter
            mount: userMedium

我有一个带有user_adapter的用户文件系统链接,可以将我的映像加载到我的bucket的这个文件夹中。

其他(如userThumbnail和userMedium(将用于liip_imagine过滤器自动生成的缓存图像。我只为下一步需要获得裁剪图像时配置了它们

配置liip_imagine

liip_imagine:
driver: "gd"
loaders:
    user_loader:
        flysystem:
            filesystem_service: oneup_flysystem.user_filesystem
resolvers:
    aws_s3_resolver:
        aws_s3:
            bucket: '%env(IONOS_S3_BUCKET_NAME)%'
            client_config:
                credentials:
                    key: '%env(IONOS_S3_ACCESS_ID)%'
                    secret: '%env(IONOS_S3_ACCESS_SECRET)%'
                endpoint: '%env(IONOS_S3_ENDPOINT)%'
                region: '%env(IONOS_S3_REGION)%'
                version: '%env(IONOS_S3_VERSION)%'
            acl: private
            cache_prefix: cache
            get_options:
                Scheme: 'https'
            put_options:
                CacheControl: 'max-age=86400'
cache: aws_s3_resolver
filter_sets:
    cache: ~
    user_thumbnail:
        cache: aws_s3_resolver
        quality: 75
        filters:
            thumbnail: { size: [ 130, 130 ], mode: outbound }
        data_loader: user_loader
    user_medium:
        cache: aws_s3_resolver
        quality: 75
        filters:
            thumbnail: { size: [ 302, 180 ], mode: outbound }
        data_loader: user_loader

为了将我的文件作为缓存文件夹中的私有文件,我为aws_s3_resolver配置了私有的acl

现在,当我想转到liip_imagine生成的url时,我得到了拒绝访问。为了最终获得资源,我需要更改liip_imagine使用签名url进行的重定向。因此,我创建了一个订阅者来捕捉解析后事件。

使用事件liip_imagine.post_resolve配置订阅者

namespace AppEventSubscriber;
use AppEntityMedia;
use AppEnumMediaFilterEnum;
use AppRepositoryMediaRepository;
use LeagueFlysystemFilesystemOperator;
use LiipImagineBundleEventsCacheResolveEvent;
use SymfonyComponentEventDispatcherEventSubscriberInterface;
class LiipImagineFilterSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private readonly MediaRepository $mediaRepository,
        private readonly FilesystemOperator $userThumbnailFilesystem,
        private readonly FilesystemOperator $userMediumFilesystem
    )
    {
    }
    public function onPostResolve(CacheResolveEvent $event): void
    {
        $media = $this->mediaRepository->findOneBy(['photo' => $event->getPath()]);
        $filter = $event->getFilter();
        if ($media instanceof Media) {
            $date = new DateTime();
            $date = $date->add(new DateInterval('PT10M'));
            if ($filter === MediaFilterEnum::USER_THUMBNAIL->value) {
                    $path = $this->userThumbnailFilesystem->temporaryUrl($media->getPhoto(), $date);
            }
            else if ($filter === MediaFilterEnum::USER_MEDIUM->value) {
                    $path = $this->userMediumFilesystem->temporaryUrl($media->getPhoto(), $date);
            }
            if (isset($path)) {
                $event->setUrl($path);
            }
        }
    }
    public static function getSubscribedEvents(): array
    {
        return [
            'liip_imagine.post_resolve' => 'onPostResolve'
        ];
    }
}

最新更新