How to get errors that correspond to each file using jQuery BlueImp upload with multiple files + symfony3
Asked Answered
R

1

6

INTRODUCTION

In order to upload multiple files to the server I am using:

  1. Symfony v3.2.6
  2. OneUpUploaderBundle
  3. OneUpFlysystemBundle
  4. jQuery File Upload by Blueimp

NOTE

Please note that:

  1. 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.
  2. I did not succeed in implementing jQuery File Upload example Basic Plus UI user interface. (Also, I did not find any relevant example on the Internet).
  3. 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) and upload 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>&nbsp;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

  1. What am I missing?
  2. Am I overlooking some parameter in configuration?
  3. Might it be a bug in jQuery File Upload by Blueimp javascript 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.

Reinertson answered 14/3, 2017 at 21:45 Comment(5)
Why in your example 2, the json returned has a property "files" containing an object whereas in the example 1, the json has a property files that contains an array of objects ? Maybe this is why you get undefined when you try to loop over the response in the example 3.Makowski
@Makowski Thanks for noticing discrepancy in response of example 1 and 2 - good catch! In example 2 I used code form OneUpUploaderBundle example on githubReinertson
@Makowski Could you show me how to return array of objects in example 2?Reinertson
Try this: $response['files'][] = [ 'name'=> $file->getBaseName(), 'type'=> $file->getType(), 'size'=> $file->getSize(), ];Makowski
Tried it, but it did not work: Notice: Indirect modification of overloaded element of Oneup\UploaderBundle\Uploader\Response\EmptyResponse has no effectReinertson
C
0

In your php.ini, do you increased the value of upload_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: Get error for ajax request

Confrere answered 21/3, 2017 at 2:20 Comment(2)
In order to test: I am uploading the same 3 files (one below 1 MB and 2 over 1MB). I am setting maximum upload size to 1048576 bytes (in oneUpUplaoderBundle config and in javascript). So I should get 2 errors for my 3 uploaded files. Please see relevant php.ini setting in update 1 section of my questionReinertson
I commented out section of my JavaScript code that handles file size checking in order to test server response. So server check of file size should respond with errors for corresponding files.Reinertson

© 2022 - 2024 — McMap. All rights reserved.