INTRODUCTION
In order to upload multiple files to the server I am using:
- Symfony v3.2.6
- OneUpUploaderBundle
- OneUpFlysystemBundle
- jQuery File Upload by Blueimp
NOTE
Please note that:
- this configuration works without a hitch when using single file uploads (chose file, upload it and then repeat from the start). My problem lies with multiple file uploads using same building blocks.
- I did not succeed in implementing
jQuery File UploadexampleBasic Plus UIuser interface. (Also, I did not find any relevant example on the Internet). - At the moment multiple file upload works just fine, though interface is "very Spartan" - it consists only of
upload progress bar(common for all files) andupload button(to upload all added files) So there is practically no UI!
TARGET
I would like to create multiple file upload that would be close to jQuery File Upload example Basic Plus UI, but:
- without file and image preview,
- without individual file upload option,
- without individual upload progress bar option.
PROBLEM
There is no way (at least visible to me at the moment) to identify which file gets an error!
Example 1
For example: I get following JSON response from the server
data.jqXHR.responseText = {"files":[{"error":"error.maxsize"},{"error":"error.maxsize"}]}
But at the time there was 3 uploaded files - and so - there is no information which error corresponds to which file!
Example 2
If I modify upload listener like so:
public function onUpload(PreUploadEvent $event)
{
$file = $event->getFile();
$response = $event->getResponse();
$response['files'] = [
'name'=> $file->getBaseName(),
'type'=> $file->getType(),
'size'=> $file->getSize(),
];
return json_encode($response);
}
I then get broken response
data.jqXHR.responseText = {"files":{"name":"php406E.tmp","type":"file","size":863329,"0":{"error":"error.maxsize"}}}
For the same 3 file upload - there should have been 2 errors, but there is only one error!
Example 3
I tried to use suggested code example,
for (k=0; k<data.files.length; k++)
{
alert(data.files[k].name + "\n" + data.files[k].error);
}
but, sadly it did not work out... data.files[k].error got undefined on every step of the loop.
CODE
My template with relevant javascript code
{% 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 title %}Upload nr.3 multiple files{% endblock %}
{% block content %}
<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> Choose files...</span>
<input id="file-upload" type="file" name="files[]" data-url="{{ oneup_uploader_endpoint('gallery') }}" multiple="multiple" />
</span>
<button id="file-upload-start" type="button" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start upload</span>
</button>
</form>
</div>
<div id="box-progress">
<div id="box-progress-bar" style="width: 0%;"></div>
</div>
<div id="box-info">
<p id="upload-status">Upload status...</p>
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript" src="{{ asset('js/tmpl/tmpl.min.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';
var GLOBAL = {};
GLOBAL.upload_url = "{{ oneup_uploader_endpoint('gallery') }}";
GLOBAL.item_count_all = 1;
GLOBAL.item_count_ok = 0;
GLOBAL.file_list = [];
GLOBAL.file_list_ids_ok = [];
function enableFileUploadControl()
{
$('input#file-upload').attr('disabled', false);
}
function disableFileUploadControl()
{
$('input#file-upload').attr('disabled', true);
}
$('#file-upload').on('fileuploadprocessfail', function (e, data)
{
//alert(data.files[data.index].error);
//alert(data.files[index].error);
alert(data.files[data.index].name + "\n" + data.files[data.index].error);
/*
var file = data.files[data.index];
alert(file.error);
console.log(file.error);
*/
});
$('#file-upload').on('click', function ()
{
clearUploadedFileList();
$('#box-progress-bar').css('width', '1%');
});
$('#file-upload').fileupload(
{
formData: {extra:1},
add: function (e, data)
{
var current_item_class,
allowedTypes = 'jpg,JPG,jpeg,JPEG,png,PNG,gif,GIF',
fileName,
fileSize,
fileType,
js_allowed_upload_file_size;
fileName = data.files[0].name;
fileSize = data.files[0].size;
fileType = data.files[0].name.split('.').pop();
js_allowed_upload_file_size = 1048576;
//console.log('fileSize = '+ fileSize);
if (allowedTypes.indexOf(fileType) < 0)
{
$('#box-progress-bar').css('width', '0');
current_item_class = 'upload-item-'+ GLOBAL.item_count_all;
$('<div class="upload-item '+ current_item_class +'"/>').appendTo($('#box-info'));
$('<p/>').text(fileName).appendTo('.'+ current_item_class);
$('<p class="wrong-file-type"/>').text('Invalid file type').appendTo('.'+ current_item_class);
GLOBAL.item_count_all++;
}
/*
else if (fileSize > js_allowed_upload_file_size)
{
current_item_class = 'upload-item-'+ GLOBAL.item_count_all;
$('<div class="upload-item '+ current_item_class +'"/>').appendTo($('#box-info'));
$('<p/>').text(fileName).appendTo('.'+ current_item_class);
$('<p class="upload-error"/>').text('Max size exceeded').appendTo('.'+ current_item_class);
GLOBAL.item_count_all++;
}
*/
else
{
current_item_class = 'upload-item-'+ GLOBAL.item_count_all;
$('<div class="upload-item '+ current_item_class +'"/>').appendTo($('#box-info'));
$('<p/>').text(fileName).appendTo('.'+ current_item_class);
if ($('.button-upload').length == 0)
{
// disabling file input
$('input#file-upload').attr('disabled', true);
$('<p class="ready-to-upload"/>').text('Ready to upload').appendTo('.'+ current_item_class);
}
//console.log('global.item_count_all = '+ GLOBAL.item_count_all);
GLOBAL.file_list.push(data.files[0]);
GLOBAL.file_list_ids_ok.push(GLOBAL.item_count_all);
GLOBAL.item_count_all++;
GLOBAL.item_count_ok++;
}
},
progressall: function (e, data)
{
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#box-progress-bar').css('width', progress + '%');
},
done: function (e, data)
{
console.log('inside MAIN DONE');
var i,
k,
errorType,
message = [];
//console.log('data = '+ data);
console.log('data.jqXHR.responseText = '+ data.jqXHR.responseText);
console.log(data);
if (data.jqXHR.responseText.length > 2)
{
errorType = $.parseJSON(data.jqXHR.responseText);
errorType = errorType['files'][0]['error'];
if (errorType === "error.forbidden_mime_type")
{
message[0] = 'error';
message[1] = 'Forbidden file type';
}
else if (errorType === "error.mime_type_mismatch")
{
message[0] = 'error';
message[1] = 'Invalid mime type';
}
else if (errorType === "error.maxsize")
{
message[0] = 'error';
message[1] = 'Max size exceeded';
}
else if (errorType === "error.whitelist")
{
message[0] = 'error';
message[1] = 'Invalid file';
}
}
else
{
message[0] = 'all is ok';
message[1] = 'No error found';
}
for (k=0; k<data.files.length; k++)
{
alert(data.files[k].name + "\n" + data.files[k].error);
i = GLOBAL.file_list_ids_ok[k];
console.log(i);
if (message[0] === 'error')
{
$('<p class="upload-error"/>').text(message).appendTo('.upload-item-'+ i);
}
else if (message[0] === 'no error')
{
$('<p class="upload-success"/>').text(message).appendTo('.upload-item-'+ i);
}
}
// after all is done
updateUploadFileListUploadFinished();
enableFileUploadControl();
resetUploadFormCounters();
},
start: function(e, data)
{
//console.log("Upload started");
console.log('inside MAIN START');
disableFileUploadControl();
updateUploadFileListUploading();
}
}
);
$('#file-upload-start').on('click', function()
{
$('#file-upload').fileupload('send',
{
files: GLOBAL.file_list,
url: GLOBAL.upload_url,
dataType: 'json',
start: function(e, data) {},
done: function (e, data) {}
}
);
});
function clearUploadedFileList()
{
$('.upload-item').remove();
}
function updateUploadFileListUploading()
{
var i,
ok_item_class;
for (i=0; i<GLOBAL.file_list_ids_ok.length; i++)
{
ok_item_class = 'upload-item-'+ GLOBAL.file_list_ids_ok[i];
$('<p class="upload-success"/>').text('Uploading...').appendTo('.'+ ok_item_class);
}
}
function updateUploadFileListUploadFinished()
{
var i,
ok_item_class;
for (i=0; i<GLOBAL.file_list_ids_ok.length; i++)
{
ok_item_class = 'upload-item-'+ GLOBAL.file_list_ids_ok[i];
$('<p class="upload-success"/>').text('Upload finished').appendTo('.'+ ok_item_class);
}
}
function resetUploadFormCounters()
{
GLOBAL.item_count_all = 1;
GLOBAL.item_count_ok = 0;
GLOBAL.file_list = [];
GLOBAL.file_list_ids_ok = [];
GLOBAL.message = [];
}
});
</script>
{% endblock %}
FINALLY
- What am I missing?
- Am I overlooking some parameter in configuration?
- Might it be a bug in
jQuery File Upload by Blueimpjavascript library?
CONCLUSION
Please advise.
Thank You for your time and knowledge.
UPDATES
Update 1
I have following settings in php.ini
- post_max_size=3G
- upload_max_filesize=3G
- max_file_uploads=20
Update 2
So I changed my Upload listener like so:
public function onUpload(PreUploadEvent $event)
{
$file = $event->getFile();
$response = $event->getResponse();
$message = [
'error' => 'none'
];
$response->addToOffset($message, array('files'));
}
And now example 2 returns:
data.jqXHR.responseText = {"files":[{"error":"none"},{"error":"error.maxsize"},{"error":"error.maxsize"}]}
I updated JavaScript part and now it is iterating through responseText and updating items with corresponding errors.
If you see/know a better way, please comment.
In your
php.ini, do you increased the value ofupload_max_filesize?Seeing your examples, it looks like you're trying to load files larger than the size allowed by the php configuration.
If you are in Firefox you can use the shortcut
Ctrl+Shift+Q, try again to load the files and look for the request with status 500, you can see the error in the Preview tab.Example: