在Symfony3

时间:2016-10-25 19:14:54

标签: jquery symfony file-upload blueimp oneupuploaderbundle

引言

我正在Windows 10 Pro开发XAMPP [1],其中包含PHP v7.0.9

我正在使用Symfony v3.1.5,OneupUploaderBundleBlueimp jQuery upload将文件上传到服务器。

在设置时我遵循了OneUpUploaderBundle [2]和jQuery file upload [3],[4]的文档。

问题

我想将文件上传到某个目录,然后检查他们的mime type并验证是允许上传的文件mime类型,之后 - 将它们移动到自定义目录(可以从文件更改为文件),最后我想要将文件路径和文件名保存到数据库。

文件上传工作正常,文件上传到oneup_uploader_endpoint('gallery')。即使自定义文件Namer也可以工作,并允许上传到自定义目录。

调用侦听器,但它们显示在Symfony Profiler事件部分Not Called Listeners中。我怀疑它可能是因为由Blueimp jQuery uploader执行的XMLHttpRequest(Ajax请求),以便上传文件和显示上传进度。

目前我使用Javascript过滤允许的mime类型。它有所帮助,但它不值得信赖"。例如,如果存在名称为test.pdf.jpg的PDF文件,则javascript将允许基于白名单中的扩展名。但是,如果PDF文件的名称为test.jpg,那么没有人可以确定真正的mimetype。因此需要在服务器上进行验证。我也在服务器端使用mimetype过滤器。

问题是 - 如果文件mimetype不在列表中 - 文件,简单地说,不会在目标目录中移动 - 从技术上讲,它上传很好,因为完全上传后服务器上的验证发生了。 (如果我理解正确的话。如果我错了,请纠正我。)而且我也不知道如何向用户显示/显示有关上传被mimetype过滤器(白名单)过滤的任何消息。

问题

所以问题是:在Blueimp jQuery上传程序成功上传文件之后,如何向用户显示关于未放入白名单的文件的反馈。

CODE

我的services.yml

services:
    app.ultra_helpers:
        class: AppBundle\UltraHelpers\UltraHelpers
        arguments: ['@service_container']

    app.upload_listener:
        class: AppBundle\EventListener\UploadListener
        arguments: ["@doctrine.orm.entity_manager", "@session", "@service_container"]
        tags:
            - { name: kernel.event_listener, event: oneup_uploader.pre_upload.gallery, method: onUpload }
            - { name: kernel.event_listener, event: oneup_uploader.post_upload.gallery, method: onPostUpload }

    app.alowed_mimetype_listener:
        class: AppBundle\EventListener\AllowedMimetypeValidationListener
        tags:
            - { name: kernel.event_listener, event: oneup_uploader.validation.gallery, method: onValidate }

    app.upload_unique_namer:
        class: AppBundle\Uploader\Naming\UploadUniqueNamer
        arguments: ["@session"]

我的自定义名称

<?php

namespace AppBundle\Uploader\Naming;

use Oneup\UploaderBundle\Uploader\File\FileInterface;
use Oneup\UploaderBundle\Uploader\Naming\NamerInterface;
use Symfony\Component\HttpFoundation\Session\Session;

class UploadUniqueNamer implements NamerInterface
{
    private $session;

    public function __construct(Session $session)
    {
        $this->session = $session;
    }

    /**
     * Creates a user directory name for the file being uploaded.
     *
     * @param FileInterface $file
     * @return string The directory name.
     */
    public function name(FileInterface $file)
    {
        $active_project_name = $this->session->get('active_project_name');
        $active_project_path = $this->session->get('active_project_path');
        $upload_files_path = $active_project_name . $active_project_path;
        $unique_name = uniqid();

        return sprintf('%s/%s_%s',
            $upload_files_path,
            $unique_name,
            $file->getClientOriginalName()
        );
    }
}

我的config.yml

oneup_uploader:
    mappings:
        gallery:
            storage:
                type: flysystem
                filesystem: oneup_flysystem.gallery_filesystem

            frontend: blueimp
            enable_progress: true
            namer: app.upload_unique_namer

            allowed_mimetypes: [ image/png, image/jpg, image/jpeg, image/gif ]
            max_size: 10485760s

oneup_flysystem:
    adapters:
        my_adapter:
            local:
                directory: "%kernel.root_dir%/../data"

    filesystems:
        gallery:
            adapter: my_adapter

我的上传监听器:

<?php

namespace AppBundle\EventListener;

use Oneup\UploaderBundle\Event\PreUploadEvent;
use Oneup\UploaderBundle\Event\PostUploadEvent;
use Doctrine\ORM\EntityManager;
use Symfony\Component\DependencyInjection\Container as Container;
use Symfony\Component\HttpFoundation\Session\Session;
use AppBundle\Entity\MyFile;

class UploadListener
{
    /**
     * @var EntityManager
     */
    private $entityManager;

    /**
     * @var Session
     */
    private $session;

    /**
     * @var Container
     */
    private $container;

    /**
     * @var originalName
     */
    protected $originalName;

    public function __construct(EntityManager $entityManager, Session $session, Container $container)
    {
        $this->entityManager = $entityManager;
        $this->session = $session;
        $this->container = $container;
    }

    public function onUpload(PreUploadEvent $event)
    {
        $file = $event->getFile();
        $this->originalName = $file->getClientOriginalName();
    }

    public function onPostUpload(PostUploadEvent $event)
    {
        $ultra = $this->container->get('app.ultra_helpers');
        $file_path = $ultra->filterFileNameFromPath($event->getFile());

        $upload_files_path = $this->session->get('active_project_path');

        $my_file = new MyFile();
        $my_file->setName($upload_files_path);
        $my_file->setFile($file_path);
        $this->entityManager->persist($my_file);
        $this->entityManager->flush();
    }
}

我的模板显示上传表单upload.html.twig

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

{% block stylesheets %}
    {{ parent() }}
    <link rel="stylesheet" type="text/css" href="{{ asset('css/blueimp/jquery.fileupload.css') }}" />
    <link rel="stylesheet" type="text/css" href="{{ asset('css/bootstrap/bootstrap.css') }}" />
    <link rel="stylesheet" type="text/css" href="{{ asset('css/bootstrap/bootstrap-theme.css') }}" />
{% endblock %}

{% block content %}
    <div id="box-list" class="clearfix">
        Go to: <a href="{{ path('file_list') }}">File list</a>
    </div>
    <div id="box-upload">
        <div id="box-file-upload">
            {{ form_start(form, {'attr': {'id': 'my-form-upload'}, 'method': 'POST'}) }}
                <div class="row form-message">
                    {{ form_errors(form) }}
                </div>
                <span class="btn btn-success fileinput-button">
                    <i class="glyphicon glyphicon-plus"></i>
                    <span>&nbsp;Choose files...</span>
                    {{ form_row(form.file, {'id': 'file-upload', 'attr': {'name': 'files[]', 'data-url': oneup_uploader_endpoint("gallery") }}) }}
                </span>
            {{ form_end(form) }}
        </div>
        <div id="box-progress">
            <div id="box-progress-bar" style="width: 0%;"></div>
        </div>
        <div id="box-info">
            <p>Upload status...</p>
        </div>
    </div>
{% endblock %}

{% block javascripts %}
    {{ parent() }}
    <script type="text/javascript" src="{{ asset('js/blueimp/jquery.ui.widget.js') }}"></script>
    <script type="text/javascript" src="{{ asset('js/blueimp/jquery.iframe-transport.js') }}"></script>
    <script type="text/javascript" src="{{ asset('js/blueimp/jquery.fileupload.js') }}"></script>
    <script type="text/javascript">
        $(function()
        {
            'use strict';
            $('#file-upload').on('click', function ()
            {
                $('#box-progress-bar').css('width', '1%');
            });

            $('#file-upload').on("fileuploadprocessfail", function(e, data)
            {
                var file = data.files[data.index];
                alert(file.error);
                console.log(file.error);
            });

            $('#file-upload').fileupload({
                dataType: 'json',
                add: function (e, data)
                {
                    var fileName = data.files[0].name;
                    var fileType = data.files[0].name.split('.').pop();
                    var allowedTypes = 'jpg,JPG,jpeg,JPEG,png,PNG,gif,GIF,pdf,PDF';
                    if (allowedTypes.indexOf(fileType) < 0)
                    {
                        $('#box-progress-bar').css('width', '0');
                        $('<p/>').text(fileName).appendTo($('#box-info'));
                        $('<p class="wrong-file-type"/>').text('Invalid file type').appendTo($('#box-info'));
                        return false;
                    }
                    else
                    {
                        $('<p/>').text(fileName).appendTo($('#box-info'));
                        if ($('.button-upload').length == 0)
                        {
                            // disabling file input
                            $('input#file-upload').attr('disabled', true);

                            data.context = $('<button class="button-upload btn btn-primary start"/>').text('Upload')
                                    .appendTo($('#box-info'))
                                    .click(function ()
                                    {
                                        data.context = $('<p class="upload-success"/>').text('Uploading...').replaceAll($(this));
                                        ($('.button-cancel')).remove();
                                        data.submit();
                                    });
                            $('<button class="button-cancel btn btn-warning cancel" />').text('Cancel')
                                    .appendTo($('#box-info'))
                                    .click(function ()
                                    {
                                        $('#box-progress-bar').css('width', '0');
                                        //console.log('testing');
                                        var message = 'Upload canceled';
                                        ($('.button-upload')).remove();
                                        ($('.button-cancel')).remove();
                                        $('<p class="wrong-file-type"/>').text(message).appendTo($('#box-info'));
                                        // enabling file input
                                        $('input#file-upload').attr('disabled', false);
                                    });
                        }
                    }
                },
                progressall: function (e, data)
                {
                    var progress = parseInt(data.loaded / data.total * 100, 10);
                    $('#box-progress-bar').css('width', progress + '%');
                },
                done: function (e, data)
                {
                    data.context.text('Upload finished.');
                    // enabling file input
                    $('input#file-upload').attr('disabled', false);
                }
            });
        });
    </script>
{% endblock %}

允许的mimetype侦听器

<?php

namespace AppBundle\EventListener;

use Oneup\UploaderBundle\Event\ValidationEvent;
use Oneup\UploaderBundle\Uploader\Exception\ValidationException;

class AllowedMimetypeValidationListener
{
    public function onValidate(ValidationEvent $event)
    {
        $config = $event->getConfig();
        $file   = $event->getFile();

        if (count($config['allowed_mimetypes']) == 0)
        {
            return;
        }

        $mimetype = $file->getMimeType();

        if (!in_array($mimetype, $config['allowed_mimetypes']))
        {
            throw new ValidationException('error.whitelist');
        }
    }
}

更新

  1. 在问题
  2. 中添加了允许的mimetype侦听器代码

    结论

    请告知。

    感谢您的时间和知识。

0 个答案:

没有答案