📜  Symfony-文件上传(1)

📅  最后修改于: 2023-12-03 15:05:27.029000             🧑  作者: Mango

Symfony 文件上传

在 web 应用程序开发中,文件上传是一个十分常见的需求。Symfony 框架为我们提供了一套简单而强大的文件上传组件,可以帮助我们轻松地实现文件上传功能。

文件上传组件安装

在 Symfony 项目中,我们可以使用 Composer 来安装文件上传组件。

composer require symfony/form

安装完成后,我们就可以在控制器和模板中使用相关的类和方法,来实现文件上传功能了。

文件上传入门

要实现文件上传功能,需要在表单中设置一个 file 类型的 input 元素。在 Symfony 中,我们可以使用 FileType 类型的表单控件来实现。

// 表单类 FileUploadForm.php
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class FileUploadForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('file', FileType::class, [
            'label' => '选择文件'
        ]);
    }
}

在控制器中,我们可以通过 $form->handleRequest($request) 方法来接收表单提交的文件。处理文件过程中,可以使用 move() 方法将文件保存到本地目录。

// FileUploadController.php
use App\Form\FileUploadForm;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class FileUploadController extends AbstractController
{
    /**
     * @Route("/upload", name="upload")
     */
    public function upload(Request $request)
    {
        $form = $this->createForm(FileUploadForm::class);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $file = $form->get('file')->getData();
            $file->move('/path/to/local/directory', $file->getClientOriginalName());
        }

        return $this->render('file_upload/upload.html.twig', [
            'form' => $form->createView()
        ]);
    }
}

在模板中,我们可以使用 form_start()form_end() 函数来开始和结束表单,并使用 form_widget() 函数来渲染表单元素。

{# upload.html.twig #}
{% extends 'base.html.twig' %}

{% block body %}
    <h1>文件上传</h1>
    {{ form_start(form) }}
    {{ form_widget(form.file) }}
    {{ form_end(form) }}
{% endblock %}
控制文件上传大小和类型

在实际开发中,我们一般需要对上传文件的大小、类型等进行限制。Symfony 也为此提供了相关的配置选项。

文件上传大小限制

我们可以在上传控件对应的 FileType 类型的 options 属性中,设置 constraints -> File -> maxSize 参数来控制上传文件的大小限制。下面是一个示例:

// 表单类 FileUploadForm.php
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\File;

class FileUploadForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('file', FileType::class, [
            'label' => '选择文件',
            'constraints' => [
                new File([
                    'maxSize' => '2M',
                    'mimeTypes' => [
                        'application/pdf',
                        'application/x-pdf',
                    ],
                ])
            ],
        ]);
    }
}
文件上传类型限制

我们可以在上传控件对应的 FileType 类型的 options 属性中,设置 constraints -> File -> mimeTypes 参数来控制上传文件的类型限制。下面是一个示例:

// 表单类 FileUploadForm.php
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\File;

class FileUploadForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('file', FileType::class, [
            'label' => '选择文件',
            'constraints' => [
                new File([
                    'maxSize' => '2M',
                    'mimeTypes' => [
                        'application/pdf',
                        'application/x-pdf',
                    ],
                ])
            ],
        ]);
    }
}
文件上传多处理

Symfony 同时也提供了上传多个文件的支持。我们可以在模板中动态添加多个上传控件,并在控制器中接收多个文件并分别处理。

// 表单类 FileUploadForm.php
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class FileUploadForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('files', FileType::class, [
            'label' => '选择文件',
            'multiple' => true,
        ]);
    }
}

// FileUploadController.php
use App\Form\FileUploadForm;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class FileUploadController extends AbstractController
{
    /**
     * @Route("/upload", name="upload")
     */
    public function upload(Request $request)
    {
        $form = $this->createForm(FileUploadForm::class);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $files = $form->get('files')->getData();
            foreach ($files as $file) {
                $file->move('/path/to/local/directory', $file->getClientOriginalName());
            }
        }

        return $this->render('file_upload/upload.html.twig', [
            'form' => $form->createView()
        ]);
    }
}

// upload.html.twig
{% extends 'base.html.twig' %}

{% block body %}
    <h1>文件上传</h1>
    {{ form_start(form) }}
    <div id="files">
        {{ form_widget(form.files) }}
    </div>
    <button id="add_file" type="button">添加文件</button>
    {{ form_end(form) }}

    <script>
        $(document).ready(function () {
            $('#add_file').click(function () {
                var index = parseInt($('#files input').last().attr('id').replace('file', '')) + 1;
                $('#files').append(
                    '<input type="file" class="form-control" name="{{ form.files.vars.full_name }}[' + index + ']" id="file' + index + '">'
                );
            });
        });
    </script>
{% endblock %}
小结

Symfony 提供了简单而强大的文件上传组件,为我们实现文件上传功能提供了很大的便利。通过控制用户上传文件的大小、类型等,我们可以有效地保护应用程序的安全。同时,文件上传多处理功能也为我们提供了很大的灵活性和扩展性,能够满足各类文件上传需求的处理。