Laravel中使用AJAX实现图片选择后立即上传(无需点击事件)时的FormData构造错误问题排查
我的代码与问题
我尝试在Laravel中用AJAX实现图片上传,代码如下:
$(document).ready(function () { bsCustomFileInput.init(); $('#exampleInputFile').on('change', function(){ var file = this.files[0]; var fileType = file["type"]; var validImageTypes = ["image/gif", "image/jpeg", "image/png"]; if ($.inArray(fileType, validImageTypes) < 0) { alert('Please select a valid image in the following formats .gif, .jpeg, .png'); }else{ $.ajaxSetup({ headers: { '_token' : $('input[name=_token]').val() } }); var formData = new FormData(document.getElementById("#upload-image-form")); alert("Created FormData, " + [...formData.keys()].length + " keys in data"); $('#image-input-error').text(''); $.ajax({ type:'POST', url: `/property/images/add`, data: formData, contentType: false, processData: false, success: function(response) { if (response) { $('#exampleInputFile').reset(); $('#images').append("<img class='img-responsive' src='uploads/property/small/"+ response.path +"'/>"); alert('Image has been uploaded successfully'); } }, error: function(response){ console.log(response); $('#image-input-error').text(response.responseJSON.errors); } }); } }); });
选择图片后触发了以下错误:
Uncaught TypeError: Failed to construct 'FormData': parameter 1 is not of type 'HTMLFormElement'.
at HTMLInputElement.(add:234)
at HTMLInputElement.dispatch (jquery.min.js:2)
at HTMLInputElement.v.handle (jquery.min.js:2)
错误出在实例化FormData的行,请问我哪里操作有误?另外,如何实现无需点击事件即可完成图片上传?
解答
Hey, let's break down and fix your issues one by one:
1. 解决FormData构造错误的核心原因
你在这一行犯了一个常见的小错误:
var formData = new FormData(document.getElementById("#upload-image-form"));
document.getElementById()的参数是元素的id字符串,不需要带#前缀!带#的是jQuery选择器的语法,原生JS的getElementById只需要传纯id值。所以正确的写法应该是:
var formData = new FormData(document.getElementById("upload-image-form"));
或者如果你习惯用jQuery,也可以把jQuery对象转成原生DOM元素再传入:
var formData = new FormData($("#upload-image-form")[0]);
这两种写法都能正确获取到表单元素,从而正常构造FormData对象。
2. 代码里的其他小问题修正
- 你的
$('#exampleInputFile').reset();是无效的,因为reset()是表单元素的方法,不是单个input的方法,应该改成重置整个表单:$('#upload-image-form')[0].reset(); - 错误提示部分,
response.responseJSON.errors是一个对象,直接用text()显示会变成[object Object],可以改成提取具体的错误信息,比如:$('#image-input-error').text(Object.values(response.responseJSON.errors).join(', '));
3. 关于“无需点击事件自动上传”
其实你现在的代码已经实现了这个需求!你绑定的是#exampleInputFile的change事件,当用户选择完图片后,这个事件会自动触发,进而执行AJAX上传逻辑。只要修正前面的FormData错误,这个功能就能正常工作,不需要额外添加点击按钮。
修正后的完整代码
$(document).ready(function () { bsCustomFileInput.init(); $('#exampleInputFile').on('change', function(){ var file = this.files[0]; var fileType = file["type"]; var validImageTypes = ["image/gif", "image/jpeg", "image/png"]; if ($.inArray(fileType, validImageTypes) < 0) { alert('Please select a valid image in the following formats .gif, .jpeg, .png'); }else{ $.ajaxSetup({ headers: { '_token' : $('input[name=_token]').val() } }); // 修正FormData的获取方式 var formData = new FormData(document.getElementById("upload-image-form")); alert("Created FormData, " + [...formData.keys()].length + " keys in data"); $('#image-input-error').text(''); $.ajax({ type:'POST', url: `/property/images/add`, data: formData, contentType: false, processData: false, success: function(response) { if (response) { // 修正重置表单的方式 $('#upload-image-form')[0].reset(); $('#images').append("<img class='img-responsive' src='uploads/property/small/"+ response.path +"'/>"); alert('Image has been uploaded successfully'); } }, error: function(response){ console.log(response); // 优化错误信息显示 $('#image-input-error').text(Object.values(response.responseJSON.errors).join(', ')); } }); } }); });
内容的提问来源于stack exchange,提问作者The Only Smart Boy

