pentatrion/upload-bundle

Symfony应用的上传助手和文件管理器

安装次数: 3,309

依赖者: 0

建议者: 0

安全性: 0

星标: 4

关注者: 1

分支: 0

开放性问题: 0

类型:symfony-bundle

v1.0.1 2023-02-24 16:21 UTC

README

Symfony logo

为您的Symfony应用程序提供的UploadBundle。

此Symfony bundle提供

  • 上传助手
  • 在您的Symfony应用程序中为Mini File Manager提供端点。
  • 为上传文件提供的Twig函数
  • 表单的FilePickerType

安装

composer require pentatrion/upload-bundle

推荐的可选依赖

  • symfony/validator : 上传文件验证所需的
  • liip/imagine-bundle : 使用文件管理器时生成缩略图所需的
  • imagine/imagine : 图像修改(调整大小、裁剪、旋转)所需的
composer require symfony/validator liip/imagine-bundle imagine/imagine

其他依赖

  • symfony/security-bundle : 只有与FilePickerType一起使用时才需要

如果您已安装liip/imagine-bundle,至少配置缩略图的small过滤器。

# config/packages/pentatrion_upload.yaml
# default configuration
pentatrion_upload:
  liip_filters: ["small"]
# config/packages/liip_imagine.yaml
liip_imagine:
  driver: "gd"

  # define filters defined in pentatrion_upload.liip_filters
  filter_sets:
    small:
      filters:
        thumbnail: { size: [250, 250], mode: inset, allow_upscale: true }

在上传路径和liipImagineBundle缓存路径(public/uploadspublic/media)中创建Apache用户访问的目录

mkdir public/{uploads,media}
chmod 777 public/{uploads,media}

使用

FileHelper

在您的FormType中创建一个未映射的FileType

use App\Entity\Post;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;


class PostType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // ...
            ->add('image', FileType::class, [
                'mapped' => false,
                'required' => false
            ])
        ;
    }
    // ...
}

在您的控制器中

class PostController extends AbstractController
{
    /**
     * @Route("/{id}/edit", name="post_edit", methods={"GET","POST"})
     */
    public function edit(Request $request, Post $post, FileHelper $fileHelper): Response
    {
        $form = $this->createForm(PostType::class, $post);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $image = $form['image']->getData();
            if ($image) {
                /** @var UploadedFile $uploadedFile */
                $uploadedFile = $fileHelper->uploadFile($image, 'posts');

                //  posts/my-image.jpg
                $post->setImagePath($fileInfos->getUploadRelativePath());
            }

            $this->getDoctrine()->getManager()->flush();
            // ...
        }
        // ...
    }
}
$file // file from $_FILES
$directory = 'relative/path'; // path to add into public_uploads.

// configured in config/packages/pentatrion_upload.yaml
// pentatrion_upload.origins.<origin>
// default value public_uplads -> "%kernel.project_dir%/public/uploads"
$originName = 'public_uploads';

$options = [
  'forceFilename' => 'beach.jpg',
  'prefix' => null,           // prefix your file name 'img-'
  'guessExtension' => false,  // guess Extension from content
                              //(if you don't trust the uploader)
  'urlize' => true,           // my File Name.jPg -> my-file-name.jpg
  'unique' => true,           // suffixe your file with hash
                              // beach-[hash].jpg
];

$fileInfos = $fileHelper->uploadFile($file, $directory, $originName, $options);

print_r($fileInfos);
{
  "id": null,
  "liipId": "@public_uploads:beach.jpg",
  "mimeGroup": "image",
  "mimeType": "image/jpeg",
  "filename": "beach.jpg",
  "directory": "",
  "origin": "public_uploads",
  "imageWidth": 1200,
  "imageHeight": 1200,
  "type": "file",
  "size": 134558,
  "updatedAt": "2021-08-07T23:12:09+02:00",
  "icon": "image-jpg.svg",
  "public": false,
  "absolutePath": null,
  "uploadRelativePath": "beach.jpg"
}

Twig函数

此bundle提供2个twig函数

  • uploaded_file_web_path('path/to/file', '')
  • uploaded_image_filtered('path/to/file', 'filter', '')
class PageController extends AbstractController
{
    #[Route('/page/{slug}', name: 'page_show')]
    public function show(Page $page): Response
    {
        return $this->render('page/show.html.twig', [
            'page' => $page
        ]);
    }

在您的page/show.html.twig模板中

<!-- folder/my-uploaded-file.pdf -->
{{ page.imagePath }}

<!-- /uploads/folder/my-uploaded-file.pdf -->
{{ uploaded_file_web_path(page.imagePath) }}

<!-- /media-manager/get/show/private_uploads/folder/my-uploaded-file.pdf -->
{{ uploaded_file_web_path(page.imagePath, "private_uploads") }}

<!-- for your original -->
<!-- <img src="/uploads/folder/logo.jpg"/> -->
<img src="{{ uploaded_file_web_path(page.imagePath) }}"/>

<!-- for your cropped image (250x250px) -->
<!-- <img src="https://127.0.0.1/media/cache/resolve/small/posts/logo.jpg"/> -->
<img src="{{ uploaded_image_filtered(page.imagePath, 'small') }}"/>

<!-- <img src="https://127.0.0.1/media/cache/resolve/small/posts/logo.jpg"/> -->
<img src="{{ uploaded_image_filtered(page.imagePath, 'small', 'private_uploads') }}"/>

与Mini File Manager JS库一起使用。

此bundle已被设计为完美集成Mini File Manager

它为后端集成提供了/media-manager端点。

npm i mini-file-manager

不使用助手

<head>
  <link rel="stylesheet" href="/dist/style.css" />
</head>
<body>
  <div id="file-manager"></div>

  <script type="module">
    import { fileManager } from "mini-file-manager";
    let config = {
      "endPoint": "/media-manager",
      "entryPoints": [
        {
          "directory": "",
          "origin": "public_uploads",
          "readOnly": false,
          "icon": "fa-lock",
          "label": "Uploads",
          "webPrefix": "/uploads"
        }
      ]
    };

    fileManager("#file-manager", config);
  </script>
</body>

使用助手

use Pentatrion\UploadBundle\Service\FileManagerHelper;

class ManagerController extends AbstractController
{
    #[Route('/manager', name: 'manager')]
    public function index(FileManagerHelperInterface $fileManagerHelper): Response
    {
        $config = $fileManagerHelper->completeConfig([
            'entryPoints' => [
                [
                    'label' => 'Uploads',
                    'directory' => '',
                    'origin' => 'public_uploads',
                    'readOnly' => false,
                    'icon' => 'fa-lock'
                ]
            ],
            'fileUpload' => [
                'maxFileSize' => 10 * 1024 * 1024,
            ],
        ]);
        return $this->render('manager/index.html.twig', [
            'fileManagerConfig' => $config,
        ]);
    }
}

文件管理器的Twig模板。mini-file-manager配置放置在data-props属性中。

<head>
  <link rel="stylesheet" href="/dist/style.css" />
</head>
<body>
  <div id="file-manager" data-minifilemanager="{{ fileManagerConfig | json_encode | e('html_attr') }}"></div>

  <script type="module">
    import { fileManager } from "mini-file-manager";
    fileManager("#file-manager");
  </script>
</body>

文件选择器的Twig模板。

<head>
  <link rel="stylesheet" href="/dist/style.css" />
</head>
<body>
  <button id="find-file" data-minifilemanager="{{ fileManagerConfig | json_encode | e('html_attr') }}">Find</button>

  <script type="module">
    import { fileManagerModal } from "mini-file-manager";
    let pickerElt = document.querySelector("#file-picker");
    let options = JSON.parse(pickerElt.dataset.minifilemanager);

    pickerElt.addEventListener("click", () => {
      fileManagerModal(options, (selectedFiles) => {
        console.log(selectedFiles);
      });
      
    })
  </script>
</body>

如果您想了解更多关于配置的详细信息,请查看Mini File Manager

如果您想查看示例,请查看Mini File Manager Template

为您的表单使用mini-file-manager的FilePickerType

use Pentatrion\UploadBundle\Form\TextFilePickerType;

class AdminUserFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('poster', TextFilePickerType::class, [
                'required' => false,
                'fileManagerConfig' => [
                    'entryPoints' => [
                        [
                            'label' => 'Uploads',
                            'directory' => 'form',
                            'origin' => 'public_uploads',
                        ],
                    ],
                    'fileUpload' => [
                        'maxFileSize' => 512 * 1024 * 1024,
                    ],
                    'fileValidation' => [
                        'imageOptions' => [
                            'ratio' => 1,
                        ],
                    ],
                    'multiple' => false
                ],
            ])
        ;
    }
}

有关完整图像选项列表,请查看mini-file-manager#Configuration存储库。

为您的表单构建器添加自定义表单主题

# config/packages/twig.yaml
twig:
  default_path: "%kernel.project_dir%/templates"
  form_themes: ["_form_theme.html.twig"]

查看_form_theme.html.twig

{# templates/_form_theme.html.twig #}
{%- block file_picker_widget -%}
    {%- set attr = attr|merge({
        class: (attr.class|default('') ~ ' file-picker')|trim,
        'data-files': files,
        'data-minifilemanager': filemanager_config,
        'data-formpreview': formpreview_config
    }) -%}
    {{- block('form_widget_simple') -}}
{%- endblock -%}

高级Bundle配置

配置您的上传目录

包配置

# config/packages/pentatrion_upload.yaml
pentatrion_upload:
  # Advanced config
  # must implement UploadedFileHelperInterface
  uploaded_file_helper: 'App\Service\AppUploadedFileHelper'

  origins:
    # choose the name of your choice
    public_uploads:
      # if directory is inside %kernel.project_dir%/public, files
      # will be directly accessible.
      path: "%kernel.project_dir%/public/uploads"
      # prefix to add in order to be found by a liip_imagine loader
      liip_path: "/uploads"
    private_uploads:
      path: "%kernel.project_dir%/var/uploads"
      liip_path: ""

  # if multiple origins
  default_origin: "public_uploads"

  # when you get infos from uploaded file put filters (liip_imagine.filter_sets)
  # you want the url used with mini-file-manager, put "small" to get thumbnails
  liip_filters: ["small", "large"]

如果您设置了实现UploadedFileHelperInterface的类(file_infos_helper选项),则可以扩展UploadedFileHelper基类。

<?php
namespace App\Service;
use Pentatrion\UploadBundle\Service\UploadedFileHelper;

class AppUploadedFileHelper extends UploadedFileHelper
{
}

您必须为您的构造函数添加3个绑定

#config/services.yaml
services:
  # default configuration for services in *this* file
  _defaults:
    autowire: true # Automatically injects dependencies in your services.
    autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
    bind:
      $liipFilters: "%pentatrion_upload.liip_filters%"
      $defaultOriginName: "%pentatrion_upload.default_origin%"
      $uploadOrigins: "%pentatrion_upload.origins%"

手动安装

composer require pentatrion/vite-bundle

如果您不想使用配方或想深入了解它修改的内容。

将上传路由添加到您的Symfony应用程序。

# config/routes/pentatrion_upload.yaml

# routes starting with /media-manager
_pentatrion_upload:
  prefix: /media-manager
  resource: "@PentatrionUploadBundle/Resources/config/routing.yaml"

为您的bundle添加配置文件

# config/packages/pentatrion_upload.yaml
# default configuration
pentatrion_upload:
  uploaded_file_helper: 'Pentatrion\UploadBundle\Service\UploadedFileHelper'
  origins:
    public_uploads:
      path: "%kernel.project_dir%/public/uploads"
      liip_path: "/uploads"

  # update to ["small"] if you have installed liip/imagine-bundle
  liip_filters: []

如果您已安装liip/imagine-bundle,请添加small过滤器。

# config/packages/liip_imagine.yaml
liip_imagine:
  driver: "gd"

  # define filters defined in pentatrion_upload.liip_filters
  # (at least small filter)
  filter_sets:
    small:
      filters:
        thumbnail: { size: [250, 250], mode: inset, allow_upscale: true }

  loaders:
    default:
      filesystem:
        data_root:
          # must be linked with pentatrion_upload -> origin.[origin-name].liip_path
          - "%kernel.project_dir%/public"