Blueimp jQuery-File-Upload - Как отправить форму без прикрепленных файлов?
Я нашел решения о том, как добавлять дополнительные данные формы при отправке формы загрузки файла. Этот вопрос заключается в том, как загрузить дополнительные данные, если нет файла для загрузки.
Я использую blueimp jquery-file-upload в приложении для управления задачами, чтобы перетащить файлы и прикрепить их к задаче.
script инициализируется и настраивается, чтобы автоматически не загружать файлы при подключении файлов. В обратном вызове fileuploadadd
я прикрепляю data.submit()
к моему обработчику событий submit
. Это позволяет отправить данные задачи и файлы в один запрос POST.
Пока файлы не будут добавлены, я не могу получить доступ к файлу-upload data
, чтобы использовать функцию data.submit()
. Я приступил к работе, добавив пустой файл (а затем удалив его) при загрузке страницы, который вызовет привязку data.submit()
к кнопке отправки. Проблема в том, что плагин возвращает ошибку при попытке пропустить пустой массив файлов. Эта проблема также возникнет, если вы добавите файл, а затем удалите его перед отправкой формы.
Я искал какое-то решение для этого и выглядел высоко и низко, но ничего не смог найти в (IMHO) ужасной документации.
Посмотрите мой код ниже:
$('#post_task').fileupload({
autoUpload: false,
singleFileUploads: false,
disableImagePreview: true,
}).on('fileuploadadd', function (e, data) {
$.each(data.files, function (index, file) {
var filename = file.name,
filesize = bytesToSize(file.size)
ext = filename.substr(filename.lastIndexOf('.')+1,5),
icon = '<i class="sprite_file sprite_file-file_extension_'+ext+'"></i>',
node = $('<li/>').append($('<span/>').html(icon + filename + ' ' + filesize + '<a href="#">×</a>')).attr('data-index',index);
node.find('a').click(function(e){
e.preventDefault();
var $self = $(this),
$listItem = $self.parents('li'),
listIndex = $listItem.attr('data-index');
$listItem.remove();
$('#files li').attr('data-index',function(index){return index;});
data.files.splice(listIndex,listIndex);
console.log(data);
vardata = data;
});
$('#files').append(node);
});
$('#post_task').unbind('submit').submit(function(ev){
ev.preventDefault();
data.submit();
});
});
Ответы
Ответ 1
Я столкнулся с той же проблемой, и в итоге я добавил пустой файл перед отправкой, если нет файла.
$("#fileupload").fileupload('add', {
files: ['']
});
Это отлично работает в моей ситуации, и бэкэнд получает POST, в то время как поданный файл имеет значение null.
В большинстве браузеров (проверенных Chrome и FF) мой Backend не получит никакого файла (null), но с IE8 есть один с размером 0. Я не тестировал его ни с каким другим IE.
Ответ 2
Я просто сделал два отдельных обработчика:
$('#avatar').fileupload({
singleFileUploads: true,
multipart : true,
dataType : 'json',
autoUpload : false,
url : config.settings.api + 'services/user/updateByActivationKey',
type : 'POST',
add : function (e, data) {
submitbtn.on("click", function () {
console.log('submitting with image');
data.submit();
});
},
done : function (result) {
console.log(result);
if (!result.error) {
$('#modal-account-activated-success').modal('show');
$("#submitbtn").removeAttr('disabled');
$('#mercname').html('');
window.setTimeout(function () {
window.location.href = config.settings.user_url;
}, 3000);
} else {
//analytics.track('completeProfileError', {
// error : JSON.parse(result.responseText).error,
// activationKey: sessionStorage.getItem("activationkey")
//});
$('#modal-account-activated-error').modal('show');
$('#submitloader').html('');
$("#submitbtn").removeAttr('disabled');
}
}
,
fail : function (e) {
//analytics.track('completeProfileError', {
// error : e,
// activationKey: sessionStorage.getItem("activationkey")
//});
$('#errormessage').html(JSON.parse(e.responseText).error.messages[0]);
$('#modal-account-activated-error').modal('show');
$('#submitloader').html('');
$("#submitbtn").removeAttr('disabled');
}
});
//if no image was uploaded
submitbtn.on("click", function () {
if ($('#preview').html().length < 1) {
console.log('submitting without image');
$.ajax({
url : config.settings.api + 'services/user/updateByActivationKey',
type : 'POST',
data : JSON.stringify({
'email' : $("#email").val(),
'activationKey' : $("#activationKey").val(),
'firstName' : $("#firstname").val(),
'lastName' : $("#name").val(),
'password' : $("#password").val(),
'gender' : $("#gender").val(),
'birthdate' : $("#birthdate").val(),
'acceptedTermsAndConditions': $("#checkbox-accept-terms").val(),
'allowsDirectMarketing' : $("#checkbox-allow-marketing").val()
}),
beforeSend: function (xhr) {
xhr.setRequestHeader("Content-Type", "application/json");
},
success : function (result) {
console.log(result);
if (!result.error) {
$('#modal-account-activated-success').modal('show');
$("#submitbtn").removeAttr('disabled');
$('#mercname').html('');
window.setTimeout(function () {
window.location.href = config.settings.user_url;
}, 3000);
} else {
//analytics.track('completeProfileError', {
// error : JSON.parse(result.responseText).error,
// activationKey: sessionStorage.getItem("activationkey")
//});
$('#modal-account-activated-error').modal('show');
$('#submitloader').html('');
$("#submitbtn").removeAttr('disabled');
}
},
error : function (e) {
//analytics.track('completeProfileError', {
// error : e,
// activationKey: sessionStorage.getItem("activationkey")
//});
$('#errormessage').html(JSON.parse(e.responseText).error.messages[0]);
$('#modal-account-activated-error').modal('show');
$('#submitloader').html('');
$("#submitbtn").removeAttr('disabled');
}
})
}
});
Ответ 3
@Hirshy и @Luk, ваше решение действительно довольно элегантно и работает как шарм. Поле ввода файлов даже не отправляется на сервер, поэтому легко определить, когда файл находится в полезной нагрузке.
В моем приложении Angular у меня есть одно представление как для добавления нового документа, так и для некоторых сопутствующих данных, а также для редактирования данных и/или загрузки замещающего документа.
Вот мое решение:
/*------------------------------------------------------------------------*/
/* Prepare file uploader. */
/* */
/* jQuery-File-Upload does not submit a form unless a file has been */
/* selected. To allow this, we manually add an empty file to be uploaded, */
/* which makes the submit handler available, and we replace the submit */
/* handler with one that will submit the form without a selected file. */
/* */
/* see: http://stackoverflow.com/q/21760757/2245849. */
/*------------------------------------------------------------------------*/
var uploadForm = $('#DocumentForm');
var fileInput = $('#DocumentForm input:file');
$scope.uploadOptions =
{
url: Services.Documents.uploadRoute,
autoUpload: false,
dropZone: uploadForm,
fileInput: fileInput,
replaceFileInput: false
};
/*---------------------------------------------------------------*/
/* Initialize the uploader. This must be done with the options */
/* or an error will be thrown when an empty file is added below. */
/* It is also necessary to initialize with the options here as */
/* well as in the element html or the results are unpredictable. */
/*---------------------------------------------------------------*/
uploadForm.fileupload($scope.uploadOptions);
/*--------------------------------------------------------------------*/
/* File processing is called in the default add handler and this */
/* handler is called after a successful add. It displays the file */
/* name in the drop zone, sets the document name for a new document, */
/* and sets the submit handler to submit the form with file and data. */
/* */
/* If editing a document, a dummy empty file object is manually */
/* added to make the submit handler available so the user can make */
/* data changes without uploading a new document. */
/*--------------------------------------------------------------------*/
uploadForm.bind("fileuploadprocessdone", function(e, data)
{
/*------------------------------------------------------------*/
/* Get the user selected file object and display the name. */
/* Set the document name to the file name if not already set. */
/*------------------------------------------------------------*/
if (data.files[0].name)
{
$scope.document.file = data.files[0];
if (!$scope.document.name)
$scope.document.name = $scope.document.file.name;
MessageService.clear();
}
/*--------------------------------------*/
/* If this is the dummy file add, reset */
/* 'acceptFileTypes' to global config. */
/*--------------------------------------*/
else
delete $scope.uploadOptions.acceptFileTypes;
/*------------------------------------------------------------*/
/* Set the submit handler. We have to do this every time a */
/* file is added because 'data' is not passed to the handler. */
/*------------------------------------------------------------*/
uploadForm.unbind('submit').submit(function(e)
{
e.preventDefault();
data.submit();
});
});
/*---------------------------------------------------------------------------*/
/* If we get here, the file could not be added to the process queue most */
/* likely because it is too large or not an allowed type. This is dispatched */
/* after the add event so clear the current file and show the error message. */
/*---------------------------------------------------------------------------*/
uploadForm.bind("fileuploadprocessfail", function(e, data)
{
$scope.document.file = null;
MessageService.notice(data.files[data.index].error);
});
/*-----------------------------------------------------------------*/
/* Add a dummy empty file if not a new document so the submit */
/* handler is set and the user does not have to upload a document. */
/*-----------------------------------------------------------------*/
if (!$scope.new_document)
{
$scope.uploadOptions.acceptFileTypes = null;
uploadForm.fileupload('add', { files: [{}] });
}
UPDATE
Оказывается, uploadForm.fileupload('add', { files: [''] });
приведет к тому, что исключение будет выведено в браузере, если сервер вернет состояние с ошибкой. JFU пытается назначить data.files[0].error
, а data.files [0] не существует.
Проблема обрабатывается красиво, назначая пустой массив вместо пустой строки: uploadForm.fileupload('add', { files: [[]] });
Я обновил приведенный выше пример.
ОБНОВЛЕНИЕ 2/29/16
Оказалось, что я все-таки хочу ограничить типы файлов, поэтому я изменил свой script, чтобы очистить свойство acceptFileTypes до добавления файла фиктивного файла и reset в обработчик добавления. Также было обнаружено, что я не смог получить доступ к ошибкам процесса в обработчике добавления, поэтому заменил его "fileuploadprocessdone" и обработал ошибку в файле fileuploadprocessfail.
Я обновил приведенный выше пример, но мы все еще используем JFU 5.42.0.
ВАЖНО
Я использую 5.42.0, который является очень старой версией JFU. Я не писал этот код, и моя первая попытка обновления не удалась. Когда я обновляюсь, я обновлю это решение. **
Ответ 4
Попробуйте этот puglin simpleUpload, не нужна форма
Html:
<input type="file" name="arquivo" id="simpleUpload" multiple >
<button type="button" id="enviar">Enviar</button>
JavaScript:
$('#simpleUpload').simpleUpload({
url: 'upload.php',
trigger: '#enviar',
success: function(data){
alert('Envio com sucesso');
}
});