Загрузка нескольких файлов и отображение индикатора выполнения - PullRequest
0 голосов
/ 20 февраля 2020

Я работаю над проектом (в Django), где я создал страницу, чтобы добавить информацию о файле и затем сам файл.

enter image description here

При нажатии кнопки «Больше наборов данных» добавляется еще одно поле для загрузки другого файла.

enter image description here

Это можно сделать, чтобы прикрепить столько файлов, сколько конечный пользователь хочет в одном go. Мне нужно загрузить все вложенные файлы после того, как нажата кнопка «Загрузить наборы данных» и должна отобразиться отдельная строка прогресса. До сих пор я пробежал несколько учебников, но подошел немного ближе к Vitor Freitas . JS код:

$(function(){
/*$("#add_new_dataset").click(function(){
    $(".file").click();
});*/

$(".file").fileupload({
    dataType: 'json',
    sequentialUploads: true, /* Send the files one by one */
    start: function(e){ /* When the upload process starts, show the modal */
        $("#modal-progress").modal("show");
    },
    stop: function(e){  /* When the upload progress finalizes, hide the modal */
        $("#modal-progress").modal("hide");
    },
    progressall: function(e, data){ /* Update the progress bar */
        var progress = parseInt(data.loaded / data.total * 100, 10),
            strProgress = progress + "%";
            $(".progress-bar").css({"width": strProgress});
            $(".progress-bar").text(strProgress);
    },
    done: function(e, data){
        if(data.result.is_valid){
            $("#gallery tbody").prepend(
                "<tr><td><a href='" + data.result.url + "'>" + data.result.name + "</a></td></tr>"
            );
        }
    }
})
});

Код шаблона:

<form id="form" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="container-fluid" id="datasets" style="margin: 0px; padding: 0px;">
    <div class="row" onfocusin="populateFilename(this);">
        <label class="col-md-2">User Name :</label>
        <input class="col-md-2" type="text" id="username" name="user_name" value="{{ user.username }}" readonly />
        <label class="col-md-2">Data-set :</label>
        <input class="col-md-2" type="text" placeholder="Enter dataset" name="dataset" required />
        <label class="col-md-2">Creation Date :</label>
        <input class="col-md-2" type="date" placeholder="YYYY-MM-DD" name="creation_date" required />
        <label class="col-md-2">Beam Line:</label>
        <input class="col-md-2" type="text" placeholder="Enter beam line" name="beamline" required />
        <label class="col-md-2">Data-set file:</label>
        <input class="col-md-2 file" type="file" name="file" data-url="{% url 'add_data_sets' %}" data-form-data='{"csrfmiddlewaretoken": "{{ csrf_token }}"}' required />
        <label class="filename"></label>

        <div class="modal fade" id="modal-progress" data-backdrop="static" data-keyboard="false">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h4 class="modal-title">Uploading...</h4>
                    </div>
                    <div class="modal-body">
                        <div class="progress">
                            <div class="progress-bar" role="progressbar" style="width: 0%;">0%</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<div style="align: center; margin-top: 5px;">
    <div class="container btn-group btn-group-justified btn-group-lg">
        <a onmouseup="addRow();" class="btn btn-outline-secondary" style="width: 50%;">More Datasets</a>
        <button type="submit" class="btn btn-outline-primary" name="add_new_dataset" id="add_new_dataset">Submit Data-set</button>
    </div>
</div>

Что мне делать? Я не очень хорош в AJAX, но я не вижу кода, который работает для отправки данных на серверную часть. Это так или я что-то упустил? Прошу игнорировать мое невежество на топи c и спасибо всем заранее.

РЕДАКТИРОВАТЬ: Код JS был переписан на основе некоторых ответов.

document.getElementById('add_new_dataset').onclick = function() {
    $(this).preventDefault();

    console.log('Files uploading begin');
    form_data = new FormData();
    const files = document.getElementsByName('file');
    let count = 0;
    for(let i = 0; i < files.length; i++){
        count++;
        form_data.append("file", files[i]);
    }

    $.ajax({
        url: "/add_data_sets",
        dataType: 'json',
        contentType: false,
        processData: false,
        data: form_data,
        type: 'POST',
        success: function(files, response, xhr, pd){
            $('.file').show();
            if(files.status != false){
                $('.progress-bar').val('/location/' + files.filename);

                var fileData = files.filename;
                console.log('Files uploading...');
            }
            else{
                alert(files.filename);
            }
        },
        /*xhrFields: {
            onprogress: function(e) {
                if(e.lengthComputable) {
                    let percentCompleted = e.loaded / evt.total;
                    pBar.style.width = percentComplete;
                    pBar.innerHTML = percentComplete + "%";
                    console.log('Percent complete : ' + percentComplete);
                }
            }
        }*/
        xhr: function(){
            let xhr = $.ajaxSettings.xhr();
            xhr.upload.onprogress = function(e) {
                let percentCompleted = e.loaded / evt.total * 100;
                pBar.style.width = percentComplete;
                pBar.innerHTML = percentComplete + "%";
                console.log('Percent complete : ' + percentComplete);
            };
            return xhr;
        }

    });
//});
};

Это просто блок кода загрузки. Отправка данных с клиентской стороны на серверную работает отлично, но это вызывает подозрение, поскольку вызовы console.log не запускаются при прохождении через него кода. Это так, что данные, так или иначе, передаются нормально, и этот код ничего не делает. EDIT2: Новая JS функция:

function upload() {
        console.log('Upload function begins');
        let pBar = document.getElementsByClassName('progress-bar')[0],
            progressWindow = document.getElementById('modal-progress'),
            formData = new FormData(document.forms.form),
            xhr = new XMLHttpRequest(),
            percent = 0;

        console.log('Form Data created');
        // Start upload
        xhr.upload.onloadstart = function() {
            //$('#modal-progress').hide().fadeIn();
            //progressWindow
        };

        // Track upload progress
        xhr.upload.onprogress = function(event) {
            percent = parseInt(event.loaded / event.total * 100);
            pBar.innerHTML = percent + "%";
            pBar.style.width = percent + "%";
            //console.log(percent + '% completed');
            //console.log('Uploaded event.loaded of event.total');
        };

        // Report if ends with an error
        xhr.upload.onerror = function() {
            console.log('An error has occurred')
        };

        // Track completion: Both successful or not
        xhr.upload.onloadend = function() {
            //$('#modal-progress').fadeOut().hide();
            console.log('Upload complete with or without error ' + xhr.status);
        };

        // Track progress: Triggered on successful completion
        xhr.upload.onload = function() {
            console.log('Uploading complete');
            progressWindow.hidden = True;
        };

        xhr.open("POST", "{% url 'add_data_sets' %}", true);

        // The 'setRequestHeader' function can only be called when xhr is opened.
        //xhr.setRequestHeader('csrfmiddlewaretoken', '{{ csrf_token }}');
        //xhr.setRequestHeader('test-info', 'something');
        xhr.setRequestHeader('Content-Type', 'application/gzip');

        xhr.send(formData);
    }

Теперь функция работает нормально. Он отправляет данные полностью нормально, но на экране консоли сервера разработки я получаю эту ошибку.

Forbidden (CSRF token missing or incorrect.): /accounts/add_data_set/
[22/Feb/2020 15:36:06] "POST /accounts/add_data_set/ HTTP/1.1" 403 2513

Я даже проверил, вошли ли данные POST, отправляемые на сервер, и они содержат токен csrf

<QueryDict: {'csrfmiddlewaretoken': ['WREoIV0aY4B2XyrU7d9Qw8kMwiokXqwWsmbc2QSHX5VQ0EaYjjeuv7PeysMJjecp'], 'user_name': ['rakesh'], 'dataset': ['r'], 'creation_date': ['2020-02-22'], 'beamline': ['r']}>

Я немного растерялся. Это проблема?

1 Ответ

1 голос
/ 20 февраля 2020

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

var form_data = new FormData();                  
        var totalFiles = document.getElementById('file').files.length;
        var count = 0;
        for (var i = 0; i < totalFiles; i++) {
            var file = document.getElementById('file').files[i];
            count++;
            form_data.append("file", file);
        }


$.ajax({
            url: "/uploadingaction",
            dataType: 'json',           
            contentType: false,
            processData: false,
            data: form_data,                             
            type: 'POST',
            success: function (files, response, xhr, pd) {
                $('yourloaderid').hide();                
                if (files.status != false) {                   
                    $('#displayid').val('/location/' + files.filename);

                    var filedata = files.filename;                                        

                } else {
                    alert(files.filename);
                }

            }
        })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...