iiirxs/image-upload-bundle

一个用于处理带有映射图像集合的多个图像上传的 Symfony 扩展包

安装: 51

依赖项: 0

建议者: 0

安全: 0

星星: 0

关注者: 2

分支: 0

开放问题: 0

类型:symfony-bundle

v1.4.4 2020-04-24 20:53 UTC

This package is auto-updated.

Last update: 2024-09-25 06:12:19 UTC


README

此扩展包为嵌入式图像集合提供开箱即用的图像上传和优化功能。

安装

请确保已全局安装 Composer,如 Composer 文档中的安装章节所述。

使用 Symfony Flex 的应用程序

打开命令控制台,进入您的项目目录,并执行以下命令

$ composer require iiirxs/image-upload-bundle

不使用 Symfony Flex 的应用程序

步骤 1:下载扩展包

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

$ composer require iiirxs/image-upload-bundle

步骤 2:启用扩展包

然后,通过将其添加到项目 config/bundles.php 文件中注册的扩展包列表中,来启用扩展包。

// config/bundles.php

return [
    // ...
    IIIRxs\ImageUploadBundle\IIIRxsImageUploadBundle::class => ['all' => true],
];

使用方法

该扩展包提供所有必要的图像上传功能,以及通过配置、服务覆盖和类继承进行扩展的能力。目前它只支持 MongoDB 数据库,通过 Doctrine ODM 扩展包。

基本使用方法

步骤 1:添加图像嵌入式集合

在文档内嵌入图像集合。目标文档类 必须 扩展 IIIRxs\ImageUploadBundle\Document\AbstractImage

AbstractImage 类提供两个基本映射字段:pathrank,但可以在扩展类中添加任何其他映射字段。

// src/Document/ImageContainer.php

/**
 * @MongoDB\EmbedMany(targetDocument=Image::class, strategy="atomicSetArray")
 */
protected $images;
// src/Document/Image.php
use IIIRxs\ImageUploadBundle\Document\AbstractImage;

/**
 * @MongoDB\EmbeddedDocument
 */ 
class Image extends AbstractImage

步骤 2:设置上传器

为了在文件系统中上传图像,您的应用程序应包含至少一个实现 IIIRxs\ImageUploadBundle\Uploader\ImageUploaderInterface 的服务,并将其添加到 IIIRxs\ImageUploadBundle\Uploader\ChainUploader

实现这一点的最简单方法是简单地配置图像应上传到的目录的完整路径。您可以通过在扩展包的配置文件中配置 default_image_upload_dir 值来完成此操作。

// config/packages/iiirxs_image_upload.yaml
iiirxs_image_upload:
    default_image_upload_dir: '%kernel.project_dir%/public/images'

该扩展包还提供创建每个上传图像的优化版本和缩略图的能力,而不仅仅是将上传的文件移动到目标目录。要使用此功能,只需提供一个包含 optimizedthumbnails 键的数组,而不是单个路径即可。

// config/packages/iiirxs_image_upload.yaml
iiirxs_image_upload:
    default_image_upload_dir:
        optimized: '%kernel.project_dir%/public/images/optimized'
        thumbnails: '%kernel.project_dir%/public/images/thumbnails'

现在,默认上传器已注册在链上传器中,并将用于上传应用程序中配置为通过扩展包处理的任何图像集合中的图像。

步骤 3:上传图像文件

由于所有必要的功能都已实现在 IIIRxs\ImageUploadBundle\Controller\ImageController 中,您只需向 uploadImages 控制器操作发出适当的请求即可。

创建图像集合

全部上传

要在一个请求中上传一个包含其排名的新图像集合,您应在 JavaScript 代码中向您的 iiirxs_image_upload 路由发出一个 POST 请求,并将 Content-Type 标头设置为 multipart/form-data。请求的有效负载应为 FormData 对象。

示例:将图像集合添加到现有的图像容器对象中

let formData = new FormData();
// name of the property containing the embedded collection 
let formField = 'images';
let imageInput = document.querySelector('#multiple_image_file_input');

formData.append(formField + '[0][file]', imageInput.files[0]);
formData.append(formField + '[0][rank]', 1);

formData.append(formField + '[1][file]', imageInput.files[1]);
formData.append(formField + '[1][rank]', 2);

// the object id to which images are being added
let id = 1;

// name of the class with the embedded collection
// route path: /{className}/{fieldName}/upload/{id}
let route = '/image-container-class/images/upload/' + id;

axios.post(route, formData);
逐个上传

要逐个上传包含 n 个图像的新图像集合,您应向 iiirxs_image_upload 路由发出 n+1 个 POST 请求;每个图像一个,加上一个图像排名。

示例:通过多个请求添加图像集合

let formField = 'images';
// the object id to which images are being added
let id = 1;

// name of the class with the embedded collection
// route path: /{className}/{fieldName}/upload/{id}
let route = '/image-container-class/images/upload/' + id;

let formData = new FormData();
// name of the property containing the embedded collection 
let imageInput = document.querySelector('#multiple_image_file_input');

formData.append(formField + '[0][file]', imageInput.files[0]);
formData.append(formField + '[1][file]', null);
let request1 = axios.post(route, formData);

formData = new FormData();
formData.append(formField + '[0][file]', null);
formData.append(formField + '[1][file]', imageInput.files[1]);
let request2 = axios.post(route, formData);

axios.all([request1, request2]).then(() => {
    let rankData = new FormData();
    rankData.append(formField + '[0][rank]', 1);
    rankData.append(formField + '[1][rank]', 2);

    axios.post(route, rankData);
})

添加到图像集合

将新图像添加到现有集合与创建图像集合的过程非常相似,涉及多个请求。请注意,在这些请求过程中,您应始终为数据库中的每张现有图像添加一个值为null的字段到FormData对象中,如果相应的排名字段未在您的FormData对象中设置,否则该图像将从数据库中删除。

示例:将新图像添加到现有集合

let formData = new FormData();
// name of the property containing the embedded collection 
let formField = 'images';
let imageInput = document.querySelector('#image_file_input');

// A third image is being added
formData.append(formField + '[2][file]', imageInput.files[0]);

formData.append(formField + '[0][rank]', 1);
formData.append(formField + '[1][rank]', 2);
formData.append(formField + '[2][rank]', 3);

// the object id to which images are being added
let id = 1;

// name of the class with the embedded collection
// route path: /{className}/{fieldName}/upload/{id}
let route = '/image-container-class/images/upload/' + id;

axios.post(route, formData);

示例:将新图像添加到现有集合(无排名)

let formData = new FormData();
// name of the property containing the embedded collection 
let formField = 'images';
let imageInput = document.querySelector('#image_file_input');

// A third image is being added
formData.append(formField + '[0][file]', null);
formData.append(formField + '[1][file]', null);
formData.append(formField + '[2][file]', imageInput.files[0]);

// the object id to which images are being added
let id = 1;

// name of the class with the embedded collection
// route path: /{className}/{fieldName}/upload/{id}
let route = '/image-container-class/images/upload/' + id;

axios.post(route, formData);

从图像集合中删除

为了从集合中删除图像,您只需从发送到FormData对象的键中省略即可。

示例:将新图像添加到现有集合(无排名)

let formData = new FormData();
// name of the property containing the embedded collection 
let formField = 'images';

// Second image is being deleted
formData.append(formField + '[0][file]', null);
formData.append(formField + '[2][file]', null);

// the object id to which images are being added
let id = 1;

// name of the class with the embedded collection
// route path: /{className}/{fieldName}/upload/{id}
let route = '/image-container-class/images/upload/' + id;

axios.post(route, formData);

步骤4(可选):发布额外的图像详情

如果您在Image类中添加了额外的字段(例如,描述),您可以将这些详细信息发布到postImageDetails控制器操作。

但是,为了做到这一点,首先您应该创建自己的表单类型类,该类扩展了IIIRxs\ImageUploadBundle\Form\Type\ImageType类。

class CustomImageType extends ImageType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        $builder
            ->add('description', TextType::class)
        ;
    }
}

然后您必须将适当的映射添加到包的配置中,以便为特定的嵌入式集合使用正确的表单类型。

// config/packages/iiirxs_image_upload.yaml

iiirxs_image_upload:
    mappings:
        App\Document\ImageContainerClass:
            fields:
                # name of the property containing the image collection
                images:
                    class: App\Document\CustomImage
                    form_type: App\Form\Type\CustomImageType

现在您可以通过向iiirxs_image_upload_details_post路由发送简单的POST请求来发布图像详情。请求的有效负载应该是一个具有示例结构的json对象。

示例:向现有图像集合发布额外详情

// name of the property containing the embedded collection 
let formField = 'images';
let details = {
    [formField]: {
        0: { rank: 1, description: 'Lorem ipsum' },
        1: { rank: 2, description: 'dolor sit amet' },
    }
}

// the object id to which images are being added
let id = 1;

// name of the class with the embedded collection
// route path: /{className}/{fieldName}/details/{id}
let route = '/image-container-class/details/' + id;

axios.post(route, details);

您已完成操作!您的图像将被存储在MongoDB数据库中的嵌入式集合中,并且相应的文件将被移动到文件系统中的适当位置。

高级用法

表单

该包提供两种基本的表单类型

  • IIIRxs\ImageUploadBundle\Form\Type\ImageCollectionType
  • IIIRxs\ImageUploadBundle\Form\Type\ImageType

它还提供了一个ImageFormService服务,该服务根据Doctrine ODM映射或显式配置创建基于ImageCollectionType的表单。

ImageCollectionType提供了一个集合字段(字段名应明确提供)。此集合字段的条目类型默认为ImageType类,但您可以通过包或通过适当传递表单选项来覆盖它。

ImageType仅支持扩展AbstractImage类的对象。

如果您的项目中的Doctrine ODM映射定义正确或包配置中存在正确的映射,您要为特定类创建一个ImageCollectionType表单,只需提供该类的实例和一个有效的字段名(对应于图像集合)给ImageFormService即可。

$object = new ImageContainer();

$form = $imageFormService->createForm($object, 'images');

为了显式定义特定类及其相应表单类型的映射,您可以使用包的配置,如下所示

// config/packages/iiirxs_image_upload.yaml

iiirxs_image_upload:
    mappings:
        App\Document\ImageContainer:
            fields:
                images:
                    class: App\Document\Image
                    form_type: App\Form\Type\YourOwnImageType
                anotherImageCollection:
                    class: App\Document\AnotherImageClass
                    form_type: App\Form\Type\AnotherImageType

上传器

该包提供了一个ChainUploader类,一个AbstractUploader类和一个ImageUploaderInterfaceImageUploaderInterface公开了两个方法:supportsupload

// config/services.yaml
App\Service\ImageUploader:
    tags: ['image.uploader']
    arguments:
        imagesDir: '%kernel.project_dir%/public/images'
        # in order to save both optimized and thumbnail images for each upload:     
        # imagesDir:
        #     optimized: '%kernel.project_dir%/public/images/optimized'
        #     thumbnails: '%kernel.project_dir%/public/images/thumbnails'   

创建ImageUploader类最简单的方法是扩展提供所有必要功能的IIIRxs\ImageUploadBundle\Uploader\AbstractUploader类。

在扩展AbstractUploader类时,您的ImageUploader服务在其构造函数中至少应接收两个参数。

构造函数参数
  • $imagesDir对应于图像应存储的目录的完整路径。它可以是字符串或数组,在后一种情况下,必须包含具有字符串值作为完整路径的optimizedthumbnails键的数组。
  • $maxThumbnailDimension在需要创建缩略图时使用,并定义缩略图的最大像素尺寸。默认设置为600px。
// App\Service\ImageUploader

class ImageUploader extends AbstractUploader
{
	
	function __construct(string $imagesDir, int $maxThumbnailDimension)
	{
		parent::__construct($imagesDir, $maxThumbnailDimension);
	}

	public function supports($document): bool
    {
        // return true to support every document or "$document instanceof ExampleClass"// 
        // to support upload only for specific class.
        // Note that ExampleClass is a class containing the image file, typically a// 
        // subclass of AbstractImage class  
        return true;
    }

}

您可以在包配置中轻松设置最大缩略图尺寸。

// config/packages/iiirxs_image_upload.yaml
iiirxs_image_upload:
    max_thumbnail_dimension: 400

该插件注册了所有标记为 'image.uploader' 的服务,这些服务位于 ChainUploader 类中。要在服务中使用 ChainUploader,您只需注入它,并调用 selectUploaderupload 方法即可。

class Service 
{
    public function __construct(ChainUploader $uploader)
    {
        $this->uploader = $uploader;
    }
    
    public function callUploader()
    {
        $this->uploader->selectUploader($image);
        $filename = $this->uploader->upload($image->getFile());
    }
}

事件

该插件提供了三个事件

  • ImageDetailsPostEvent
  • ImagesDeleteEvent
  • ImagesUploadEvent

以及一个事件订阅者,它监听 ImagesDeleteEventImagesUploadEvent 事件。该 ImageListener 使用 ChainUploader 服务适当上传文件,并在正确分发 ImagesDeleteEvent 时删除图像文件。

您可以通过覆盖项目配置中的 iiirxs_image_upload.event_listener.image_listener 服务来为该事件订阅者设置自己的功能。

控制器

该插件最终提供了处理与图像上传相关的所有内容的控制器操作。

如前所述,如果您想使用插件提供的控制器操作,您只需注册至少一个实现 ImageUploaderInterface 的服务,并标记为 'image.uploader',且支持您想要的上传情况即可。

该插件提供了两种不同的操作:用于文件上传的 uploadImages 和用于更新图像相关信息的 postImageDetails(如图像排名和图像描述)。

目前,uploadImages 操作仅支持通过表单提交(multipart/form-data 内容类型)进行文件上传。