Как получить ошибки, соответствующие каждому файлу, используя загрузку jQuery BlueImp с несколькими файлами + symfony3

ВСТУПЛЕНИЕ

Чтобы загрузить несколько файлов на сервер, я использую:

  1. Симфони v3.2.6
  2. OneUpUploaderBundle
  3. OneUpFlysystemBundle
  4. Загрузка файла jQuery с помощью Blueimp

ПРИМЕЧАНИЕ

Обратите внимание, что:

  1. эта конфигурация работает без сбоев при использовании загрузки одного файла (выберите файл, загрузите его, а затем повторите сначала). Моя проблема заключается в загрузке нескольких файлов с использованием одних и тех же строительных блоков.
  2. Мне не удалось реализовать jQuery File Upload пример Basic Plus UI пользовательского интерфейса. (Кроме того, я не нашел ни одного подходящего примера в Интернете).
  3. На данный момент множественная загрузка файлов работает просто отлично, хотя интерфейс "очень спартанский" - он состоит только из upload progress bar (общий для всех файлов) и upload button (для загрузки всех добавленных файлов) Так что интерфейса практически нет!

ЦЕЛЬ

Я хотел бы создать несколько загрузок файлов, которые были бы близки к jQuery File Upload примеру Basic Plus UI, но:

  • без предварительного просмотра файлов и изображений,
  • без возможности загрузки отдельных файлов,
  • без отдельной опции индикатора выполнения загрузки.

ПРОБЛЕМА

Нет никакого способа (по крайней мере, видимого мне в данный момент) определить, в каком файле возникает ошибка!

Пример 1

Например: я получаю следующий ответ JSON от сервера

data.jqXHR.responseText = {"files":[{"error":"error.maxsize"},{"error":"error.maxsize"}]}

Но на тот момент было загружено 3 файла - так вот - нет информации какая ошибка какому файлу соответствует!

Пример 2

Если я изменю прослушиватель загрузки следующим образом:

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);
}

Затем я получаю сломанный ответ

data.jqXHR.responseText = {"files":{"name":"php406E.tmp","type":"file","size":863329,"0":{"error":"error.maxsize"}}}

Для тех же 3-х закачек файлов - должно было быть 2 ошибки, а тут только одна ошибка!

Пример 3

Я попытался использовать предложенный пример кода,

for (k=0; k<data.files.length; k++)
{
    alert(data.files[k].name + "\n" + data.files[k].error);
}

но, к сожалению, не получилось... data.files[k].error получил undefined на каждом шаге цикла.

КОД

Мой шаблон с соответствующим кодом javascript

{% 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 %}

В КОНЦЕ КОНЦОВ

  1. Что мне не хватает?
  2. Я пропускаю какой-то параметр в конфигурации?
  3. Может быть, это ошибка в jQuery File Upload by Blueimp библиотеке javascript?

ВЫВОД

Пожалуйста, порекомендуйте.

Спасибо за ваше время и знания.

ОБНОВЛЕНИЯ

Обновление 1

У меня есть следующие настройки в php.ini

  • post_max_size=3G
  • upload_max_filesize=3G
  • max_file_uploads=20

Обновление 2

Итак, я изменил свой Upload listener вот так:

public function onUpload(PreUploadEvent $event)
{
    $file = $event->getFile();

    $response = $event->getResponse();

    $message = [
        'error' => 'none'
    ];

    $response->addToOffset($message, array('files'));
}

И теперь пример 2 возвращает:

data.jqXHR.responseText = {"files":[{"error":"none"},{"error":"error.maxsize"},{"error":"error.maxsize"}]}

Я обновил часть JavaScript, и теперь она перебирает responseText и обновляет элементы с соответствующими ошибками.

Если вы видите/знаете лучший способ, пожалуйста, прокомментируйте.


person Rikijs    schedule 14.03.2017    source источник
comment
Почему в вашем примере 2 возвращенный json имеет файлы свойств, содержащие объект, тогда как в примере 1 у json есть файлы свойств, содержащие массив объектов? Возможно, именно поэтому вы получаете неопределенность, когда пытаетесь перебрать ответ в примере 3.   -  person Picoss    schedule 20.03.2017
comment
@Picoss Спасибо, что заметили несоответствие в ответах на примеры 1 и 2 - хороший улов! В примере 2 я использовал форму кода OneUpUploaderBundle пример на github   -  person Rikijs    schedule 21.03.2017
comment
@Picoss Не могли бы вы показать мне, как вернуть массив объектов в примере 2?   -  person Rikijs    schedule 21.03.2017
comment
Попробуйте это: $response['files'][] = [ 'name'=> $file->getBaseName(), 'type'=> $file->getType(), 'size'=> $file->getSize (), ];   -  person Picoss    schedule 21.03.2017
comment
Пробовал, но не получилось Notice: Indirect modification of overloaded element of Oneup\UploaderBundle\Uploader\Response\EmptyResponse has no effect   -  person Rikijs    schedule 21.03.2017


Ответы (1)


В своем php.ini вы увеличили значение upload_max_filesize?

Глядя на ваши примеры, похоже, вы пытаетесь загрузить файлы, размер которых превышает размер, разрешенный конфигурацией php.

Если вы находитесь в Firefox, вы можете использовать ярлык Ctrl+Shift+Q, попробовать снова загрузить файлы и найти запрос со статусом 500, вы можете увидеть ошибку на вкладке «Предварительный просмотр».

Пример: Получить ошибку для запроса ajax

person ypdieguez    schedule 21.03.2017
comment
Чтобы проверить: я загружаю те же 3 файла (один меньше 1 МБ и 2 больше 1 МБ). Я устанавливаю максимальный размер загрузки на 1048576 байт (в конфигурации oneUpUplaoderBundle и в javascript). Поэтому я должен получить 2 ошибки для моих 3 загруженных файлов. См. соответствующую настройку php.ini в разделе update 1 моего вопроса. - person Rikijs; 21.03.2017
comment
Я закомментировал раздел своего кода JavaScript, который обрабатывает проверку размера файла, чтобы проверить ответ сервера. Таким образом, серверная проверка размера файла должна отвечать ошибками для соответствующих файлов. - person Rikijs; 21.03.2017