phpjquerysymfonyblueimponeupuploaderbundle

Symfony 3.1 and OneUpUploaderBundle + Blueimp = UploadListener is not called


INTRODUCTION

Almost two weeks ago I created similar question about upload using OneupUploaderBundle, but with FineUploader library. Sadly there are no answers yet. In the meantime I tried setting up different upload library.

I am developing on Windows 10 Pro with XAMPP [1] which includes PHP v7.0.8.

I am using Symfony v3.1.5, OneupUploaderBundle and Blueimp jQuery upload in order to upload files to server.

While setting things up I followed documentation of OneUpUploaderBundle [2] and jQuery file upload [3], [4].

PROBLEM

I want to upload files to some directory and then check their mime type and validate is file mime type allowed for uploading and after that - move them to custom directory (that can change from file to file), finally i want to persist file path and file name to database.

File upload works fine and files are uploaded to oneup_uploader_endpoint('gallery'). Even custom file Namer works and allows upload to custom directory.

However, listeners are not called (upload listeners and validation) and are displayed in Symfony Profiler Events section Not Called Listeners!

That is unfortunate, as I want to save info about file to database using Post_Persist event. OneupUploaderBundle events.

CODE

my services.yml

services:
    app.upload_listener:
        class: AppBundle\EventListener\UploadListener
        arguments: ["@doctrine.orm.entity_manager"]
        tags:
            - { name: kernel.event_listener, event: oneup_uploader.post_persist.default_uploader, method: onUpload }
            - { name: kernel.event_listener, event: oneup_uploader.post_persist.default_uploader, method: onPostUpload }

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

my custom Namer

<?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)
    {
        $upload_files_path = $this->session->get('upload_files_path');
        $unique_name = uniqid();

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

my config.yml

oneup_uploader:
    mappings:
        gallery:
            frontend: blueimp
            enable_progress: true
            namer: app.upload_unique_namer
            use_orphanage: false
            allowed_mimetypes: [image/png, image/jpg, image/jpeg, image/gif]
            max_size: 200M

my upload listener:

<?php

namespace AppBundle\EventListener;

use Oneup\UploaderBundle\Event\PreUploadEvent;
use Oneup\UploaderBundle\Event\PostUploadEvent;
use Oneup\UploaderBundle\Event\PostPersistEvent;
use Doctrine\ORM\EntityManager;
use AppBundle\Entity\Product;

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

    //protected $originalName;

    public function __construct(EntityManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

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

    public function onPostUpload(PostPersistEvent $event)
    {
        $file = $event->getFile();

        $object = new Product();
        $object->setName($file->getClientOriginalName());
        //$object->setName($file->getPathName());

        $this->entityManager->persist($object);
        $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('product_list') }}">Product list</a>
    </div>
    <div id="box-upload">
        <div id="box-file-upload">
            <form method="post" enctype="multipart/form-data">
                <span class="btn btn-success fileinput-button">
                    <i class="glyphicon glyphicon-plus"></i>
                    <span>&nbsp;Choose files...</span>
                    <input id="file-upload" type="file" name="files[]" data-url="{{ oneup_uploader_endpoint('gallery') }}" />
                </span>
            </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/jquery-3.1.0.js') }}"></script>
    <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';
                    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 %}

UPDATES

  1. Added a note about development environment.
  2. Tried same code with Symfony v2.8.8, sadly UploadListener is not called.
  3. Edited services.yml, removed (I think) now unnecessary (duplicated - provided in OneupUploaderBundle) validation that I added while trying to make it work...

CONCLUSION

Please advise.

Thank You for your time and knowledge.


Solution

  • Just listen to the right event. Event exchange contains the name of your mapping, in order that you can implement a specific logic to this one that will not affect the others.

    Event to this format.

    oneup_uploader.post_upload.{mapping}
    

    In your case it will give

    oneup_uploader.post_upload.gallery
    

    For more informations, please read https://github.com/1up-lab/OneupUploaderBundle/blob/master/Resources/doc/events.md