Я работаю над проектом (в Django), где я создал страницу, чтобы добавить информацию о файле и затем сам файл.
При нажатии кнопки «Больше наборов данных» добавляется еще одно поле для загрузки другого файла.
Это можно сделать, чтобы прикрепить столько файлов, сколько конечный пользователь хочет в одном 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']}>
Я немного растерялся. Это проблема?