Rails 5:如何防止来自 jQuery 的多次提交
Posted
技术标签:
【中文标题】Rails 5:如何防止来自 jQuery 的多次提交【英文标题】:Rails 5 : How to prevent multiple submission from jQuery 【发布时间】:2018-09-11 19:26:02 【问题描述】:我是编码初学者。
我正在 Rails 5 上开发我的应用程序,并让用户使用 blueimp/jQuery-File-Upload 裁剪图像并将其从客户端直接上传到 AWS s3。
当用户重新选择要裁剪和上传的图像时,我遇到了问题。 这种重新选择会导致向 Rails 提交多个表单,最终会创建与重新选择相同数量的帖子...
我想知道如何防止这种多次提交。
我的 javascript 代码是这样的;
$(function()
$('.directUpload').find("input:file").each(function(i, elem)
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
fileInput.after(barContainer);
fileInput.fileupload(
fileInput: fileInput,
url: form.data('url'),
type: 'POST',
autoUpload: false,
formData: form.data('form-data'),
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
replaceFileInput: false,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
//trying to limit the number of files, but none of them works...
maxNumberOfFiles: 1,
sequentialUploads: true,
limitMultiFileUploads:1,
limitConcurrentUploads: 1,
add: function(e, data)
if (data.files && data.files[0])
var reader = new FileReader();
reader.onload = function(e)
$('.preview').empty();
$('.preview').append($('<img>').attr(// insert preview image
src: e.target.result,
id: "crop_img",
title: data.files[0].name
));
$('#crop_img').cropper() // initialize cropper on preview image
;
reader.readAsDataURL(data.files[0]);
// $('#clear').show();
;
// tried to clear the form and file input when re-selection occurs, however, it doesn't work either...
// $('#clear').click(function()
// $('#image').val('');
// $('.preview').empty();
// $('form').reset();
// $(this).hide();
// );
submitButton.on('click', function()
$('form').submit(function()
return false;
);
$('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob)
data.files[0] = new File([blob], data.files[0].name);
data.originalFiles[0] = data.files[0];
data.submit();
)
);
,
...
done: function(e, data)
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = '//' + form.data('host') + '/' + key;
// create hidden field
var input = $("<input />", type:'hidden', name: fileInput.attr('name'), value: url )
form.append(input);
//delete submit event which is false
$('form').off('submit');
//and submit again
$('.directUpload').submit();
...
);
);
);
【问题讨论】:
【参考方案1】:我认为这是因为每次调用add
时都会调用以下代码:
submitButton.on('click', function()
$('form').submit(function()
return false;
);
$('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob)
data.files[0] = new File([blob], data.files[0].name);
data.originalFiles[0] = data.files[0];
data.submit();
)
);
我不确定您的代码是如何工作的。因此,一种解决方案是将代码更新为:
// outside add function:
var lastData = null;
submitButton.on('click', function()
$('form').submit(function()
return false;
);
$('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob)
lastData.files[0] = new File([blob], data.files[0].name);
lastData.originalFiles[0] = lastData.files[0];
lastData.submit();
)
);
// In add function
lastData = data;
PS:lastData 是一种快速的解决方法,但我认为它不能正常工作。
$(function()
$('.directUpload').find("input:file").each(function(i, elem)
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
var lastData = null;
submitButton.on('click', function()
$('form').submit(function()
return false;
);
$('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob)
lastData.files[0] = new File([blob], data.files[0].name);
lastData.originalFiles[0] = lastData.files[0];
lastData.submit();
)
);
fileInput.after(barContainer);
fileInput.fileupload(
fileInput: fileInput,
url: form.data('url'),
type: 'POST',
autoUpload: false,
formData: form.data('form-data'),
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
replaceFileInput: false,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
//trying to limit the number of files, but none of them works...
maxNumberOfFiles: 1,
sequentialUploads: true,
limitMultiFileUploads:1,
limitConcurrentUploads: 1,
add: function(e, data)
if (data.files && data.files[0])
var reader = new FileReader();
reader.onload = function(e)
$('.preview').empty();
$('.preview').append($('<img>').attr(// insert preview image
src: e.target.result,
id: "crop_img",
title: data.files[0].name
));
$('#crop_img').cropper() // initialize cropper on preview image
;
reader.readAsDataURL(data.files[0]);
// $('#clear').show();
;
// tried to clear the form and file input when re-selection occurs, however, it doesn't work either...
// $('#clear').click(function()
// $('#image').val('');
// $('.preview').empty();
// $('form').reset();
// $(this).hide();
// );
lastData = data;
,
...
done: function(e, data)
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = '//' + form.data('host') + '/' + key;
// create hidden field
var input = $("<input />", type:'hidden', name: fileInput.attr('name'), value: url )
form.append(input);
//delete submit event which is false
$('form').off('submit');
//and submit again
$('.directUpload').submit();
...
);
);
);
【讨论】:
以上是关于Rails 5:如何防止来自 jQuery 的多次提交的主要内容,如果未能解决你的问题,请参考以下文章
Rails 4 + Turbolinks + JQuery Turbolinks + Coffeescript:事件被多次触发