Rikijs Rikijs - 1 month ago 31
jQuery Question

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.

Answer

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

Comments