<input id="importInputFile" type="file"/>
的change事件“$("#importInputFile
").change(()=>{//xxx})”只能被触发一次,不管上传失败还是成功
在标签上绑定了<input id="importFile" onchange="javascript:$('#importFileName').val()"/>
也一样
原因:
在网页上要操作文件通常会使用input[type=file]控件。它选择后会触发一个事件,只是让上面的文字改变,而这个改变会触发change事件而已,并不会自动清空已选的value。对于文字没改变的选择,或者第二次选择,change事件则不会触发。所以需要手动清空元素的value,但是部分浏览器清空会无效果,所以保守的做法是直接替换这个file元素
这里我提供两种方法
个人推荐第一种,简单粗暴明了,自用没毛病。
(最近发现直接清空value在蛮多浏览器基本都奏效了。详情看第三点 2018-10-18)
一、
每次执行完你的change函数后替换一下原来的input type=file控件
function importMaterial(obj,type){
$.ajax({
url: xxx,
type: "POST",
data: JSON.stringify(item),
headers: headersJson,
success: function (data) {
//xxx
},
error: function (data) {
console.log(data.responseText);
},
complete: function () {
$("#btn_uploadMaterial").replaceWith('<input type="file" id="btn_uploadMaterial" accept=".xls,.xlsx" onchange="importMaterial(this,'+type+')"/>'); //替换的内容可以与你原来的input一模一样,只要你执行替换,
// 浏览器就会认为你这是个新的控件,之前的记录就会被清空
//change事件就可以再次调用了
}
});
}
这里我还可以推广出另一种偷天换日的解决方案。既然值无法写入,为何我们不创建一个新的INPUT[type=file]把旧的替换掉呢?这么一来,需要解决的问题就剩下事件绑定了。这可以通过在容器上绑定事件,之后通过冒泡的方式来获取,而不把事件绑定到目标元素上的方法来解决。
二、
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script>
$(function(){
form.reset(); //清除浏览器记录的上次记录
var file;
$(form).on("change","#file",function(e){
//输出选中结果
console.log(this.value);
//每次选中都保存旧元素,并使用新的控件替换
$(this).clone().replaceAll(file=this);
}).submit(function(){
//提交时把之前保存的旧元素替换回去
$("#file").replaceWith(file);
});
});
</script>
<form id="form">
<input type="file" name="file" id="file"><br/>
<input type="submit" />
</form>
三、目前已兼容大部分浏览器,还蛮阔以
//皆为文件上传结束后再清空,否则会影响文件上传
1、jQ
$("#btn_uploadMaterial").val('');
2、vue
function fileChange(e){
e.srcElement.value = "";
}
3、dom
document.getElementById("btn_uploadMaterial").value="";