eltharin/fileuploadmanager

fileuploadmanager 用于 symfony 的包

安装: 21

依赖关系: 0

建议者: 0

安全: 0

星标: 1

关注者: 1

分支: 0

开放问题: 0

类型:symfony-bundle

V1.3.0 2024-06-01 14:32 UTC

This package is auto-updated.

Last update: 2024-10-01 00:20:46 UTC


README

Latest Stable Version Total Downloads Latest Unstable Version License

安装

  • 使用 composer 安装包
composer require eltharin/fileuploadmanager

什么是 fileuploadmanager 包?

FileUploadManager 包使文件上传变得最简单,只需少量配置,即可实现自动上传。

它是如何工作的?

您可以通过两种不同的方式保存文件

  • 内联:内容将保存在数据库中,以 base64 编码
  • 文件系统:数据库将存储文件路径

您可以选择是否为文件创建一个实体。

案例

您有一个名为 Foo 的实体,它有一个表示文件的字段 bar。Bar 是文本类型,可空(如果不是文件),对于路径,您可以设置字符串。

#[ORM\Entity(repositoryClass: FooRepository::class)]
class Foo
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $bar = null;

...

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getBar(): ?string
    {
        return $this->bar;
    }

    public function setBar(?string $bar): static
    {
        $this->bar = $bar;

        return $this;
    }

 ...
}

以下是一些不同的案例

1- 内容内联为 base64

在 FormType 中:您只需为 bar 属性添加一个项目,从 FileUploadType 中选择一些参数。

现在,如果您想将文件内容直接设置在字段中为 base64,可以设置以下选项

use Eltharin\FileUploadManagerBundle\Form\FileUploadType;

class FooType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('bar', FileUploadType::class, [
                'file_storage_inline' => true,
                'file_storage_json' => false,
            ]);
    }
}

字段内容将如下所示

iVBORw0KG`...`5ErkJggg==

2- 内容内联为 json

如果要让字段内容是一个包含名称、大小、内容和 mime-type 的 Json,选项将是

use Eltharin\FileUploadManagerBundle\Form\FileUploadType;

class FooType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('bar', FileUploadType::class, [
                'file_storage_inline' => true,
                'file_storage_json' => true, //true is the default value, you can omit this line
            ]);
    }
}

字段内容将如下所示

{"content":"iVBORw0KG`...`5ErkJggg==","name":"55c488f3e3888f054ca531dbd7252c34.png","size":81049,"mimeType":"image\/png"}

3- 内容在公共文件夹中的文件系统中为 json

如果要让字段内容是一个包含名称、大小、 mime-type 和文件路径的 Json,选项将是

use Eltharin\FileUploadManagerBundle\Form\FileUploadType;

class FooType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('bar', FileUploadType::class, [
                'file_storage_inline' => false, // false is the default value, you can omit this line
                'file_storage_json' => true, // true is the default value, you can omit this line
                'file_storage_path' => '/public/files',// "/public/files" is the default value, you can omit this line
            ]);
    }
}

字段内容将如下所示

{"path":"\/public\/files\/55c488f3e3888f054ca531dbd7252c34_65de10fd784d8.png","name":"55c488f3e3888f054ca531dbd7252c34.png","size":81049,"mimeType":"image\/png"}

4- 内容在非公共文件夹中的文件系统中为 json

如果要让字段内容是一个包含名称、大小、内容和 mime-type 的 Json

use Eltharin\FileUploadManagerBundle\Form\FileUploadType;

class FooType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('bar', FileUploadType::class, [
                'file_storage_inline' => false, // false is the default value, you can omit this line
                'file_storage_json' => true, // true is the default value, you can omit this line
                'file_storage_path' => '/var/data/files',
            ]);
    }
}

字段内容将如下所示

{"path":"\/var\/data\/files\/55c488f3e3888f054ca531dbd7252c34_65de10fd784d8.png","name":"55c488f3e3888f054ca531dbd7252c34.png","size":81049,"mimeType":"image\/png"}

如您所见,案例 3 和 4 类似,因为它们执行的是相同的操作,但是,由于文件不在公共文件夹中,系统不知道如何搜索它以使其可下载,因此在表单中链接消失。

为了解决这个问题,您可以将一个函数传递给参数:'file_downloadLink',如下所示

use Eltharin\FileUploadManagerBundle\Form\FileUploadType;

class FooType extends AbstractType
{
    public function __construct(private UrlGeneratorInterface $router)
    {

    }
    
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('bar', FileUploadType::class, [
                'file_storage_inline' => false, // false is the default value, you can omit this line
                'file_storage_json' => true, // true is the default value, you can omit this line
                'file_storage_path' => '/var/data/files',
                'file_downloadLink' => function (FormView $view) {return $this->router->generate('app_foo_showimg', ['id' => $view->parent->vars['value']->getId()]);},
            ]);
    }
}

在函数中,我们请求路由生成器获取名为 app_foo_showimg 的路由,该路由需要 Foo id 以显示关联的图片,Foo id 通过获取 $view->parent->vars['value']->getId() 获取。$view 是 UplodFormType,$view->parent 是前面的类型,因此是 FooType,获取值及其 id。

file_downloadLink 函数还用于图像类型文件的情况,在这种情况下,图像也显示在表单中,要设置此选项,必须将 'file_type' 选项设置为 'image'。

单独的实体中的文件

您可以选择将文件存储在单独的实体中,以简化数据库查询,或者为了有一个 ManyToX 关系,将许多文件关联到您的实体。

为此,您有两个 MappedSuperClass,Eltharin\FileUploadManagerBundle\Entity\FileInline 和 Eltharin\FileUploadManagerBundle\Entity\FilePath,您只需创建自己的实体,从其中一个扩展它,并创建自己的关系。

我们将将我们的 Foo 类更改为 File 实体

namespace App\Entity;

#[ORM\Entity(repositoryClass: FooRepository::class)]
class Foo
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\ManyToOne( cascade: ['persist'])]
    private ?File $fileInEntity = null;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getFileInEntity(): ?File
    {
        return $this->fileInEntity;
    }

    public function setFileInEntity(?File $fileInEntity): static
    {
        $this->fileInEntity = $fileInEntity;

        return $this;
    }
}

以及 File 实体

namespace App\Entity;

#[ORM\Entity(repositoryClass: FileRepository::class)]
class File extends \Eltharin\FileUploadManagerBundle\Entity\FileInline
{
}

现在,您只需设置实体类为

use Eltharin\FileUploadManagerBundle\Form\FileUploadType;
use App\Entity\File;

class FooType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('imageentityinline', FileUploadType::class, [
                'data_class' => File::class,
            ]);
    }
}

当使用 Eltharin\FileUploadManagerBundle\Entity\FileInline 时,可以省略 file_storage_inline 选项,它将自动设置。

您也可以使用多对多关系,并关联其所属的集合

#[ORM\Entity(repositoryClass: FooRepository::class)]
class Foo
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\ManyToMany(targetEntity: FilePath::class,cascade: ['persist'])]
    private Collection $manyimage;
    
    /**
     * @return Collection<int, FilePath>
     */
    public function getManyimage(): Collection
    {
        return $this->manyimage;
    }

    public function addManyimage(FilePath $manyimage): static
    {
        if (!$this->manyimage->contains($manyimage)) {
            $this->manyimage->add($manyimage);
        }

        return $this;
    }

    public function removeManyimage(FilePath $manyimage): static
    {
        $this->manyimage->removeElement($manyimage);

        return $this;
    }
}

表单类型

use Eltharin\FileUploadManagerBundle\Form\FileUploadType;
use App\Entity\File;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class FooType extends AbstractType
{
    public function __construct(private UrlGeneratorInterface $router)
    {

    }
    
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('manyimage', CollectionType::class,[
                'allow_add' => true,
                'allow_delete' => true,
                'required' => false,
                
                'entry_type' => FileUploadType::class,
                'entry_options' => [
                    'data_class' => File::class,
                    'file_type' => 'image',
                    'file_storage_path' => '/var/data/files',
                    'file_downloadLink' => function (FormView $view) {return $this->router->generate('app_foo_showimg2', ['foo' => $view->parent->parent->vars['value']->getId(), 'file' => $view->vars['value']->getId()]);},
                    'delete_on_remove' => false,
                ],

            ]);
    }
}

在多对多关系的情况下,请考虑将 delete_on_remove 选项设置为 false,此选项可以被对文件实体上的 onDelete 事件的 eventlistener 替换。

其他选项

  • allow_update : 允许用户通过设置 input[type=file] 来替换文件(如果已存在文件)。默认值:true;

  • allow_delete : 允许用户在不替换其他文件的情况下删除文件,在表单中会显示一个复选框。

  • upload_options : 传递给输入字段的选项

  • delete_options : 传递给删除复选框字段的选项

  • file_manager : 如果缺少某些选项,您可以创建自己的文件管理器服务

    • 您必须创建一个带有 autoConfigure 属性且标签为 app.fileManager 的类
    • 类必须实现 Eltharin\FileUploadManagerBundle\Form\FileManager\FileManagerInterface
    • 完成您自己的函数
#[Autoconfigure(tags: ['app.fileManager'])]
class FileManagerService implements FileManagerInterface
{
    public function populate(&$fileData, UploadedFile $file, $options)
	{
        ...
	}

	public function remove(&$fileData, array $options)
	{
		$fileData = null;
	}

	public function getFileViewData(FormView $view, array $options) : array
	{
	    ...
		return [
			'thumbnail' => $thumbnail,
			'download_link' => $link,
			'download_name' => $name,
		];
	}
}

并将其传递给类型选项

use Eltharin\FileUploadManagerBundle\Form\FileUploadType;
use App\Entity\File;

class FooType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('file', FileUploadType::class, [
                'file_manager' => FileManagerService::class,
            ]);
    }
}

您不喜欢我的默认值吗?

您可以在 /conf/packages/ 目录下创建一个名为 eltharin_file_upload_manager.yaml 的 Yaml(或 XML 或 PHP,根据您的配置)

并设置您自己的默认值

eltharin_file_upload_manager: default: allow_update: false allow_delete: true data_class: null delete_on_remove: false file_storage_inline: true file_manager: 'App\Service\FileManager' file_storage_json: false file_storage_path: '/public/documents'