input文件上传时取消事件监听

最近在处理文件上传时需要知道用户是否点击了取消,为此查了下可行性,这里总结下

1
<input type="file"/>

JS并不支持

首先官方没提供方案,即如果用户唤起文件选择弹窗,然后点击取消,JS是没有暴露事件告诉我们取消的,因此这里需要HACK解决下。当然如果可以接受再加一层弹窗也可以,即用户主观自己点击了下我们提供的取消按钮。

HACK方案

这里介绍下HACK方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// fileEl即inputFile
const files = await new Promise((resolve) => {
fileEl.onchange = async (_e) => {
const { files } = fileEl;
resolve(files);
};
fileEl.onclick = (_e) => {
fileEl.value = null;
};
document.body.onfocus = () => {
setTimeout(() => {
if (fileEl.files.length === 0) {
resolve(fileEl.files);
}
}, 500);
};
});
  1. onchange,onclick,onfocus的执行顺序是onfocus->onclick->onchange
  2. 用户点击取消弹窗,onfocus一定会触发,考虑到如果选择了文件也会先执行onfocus,同时因为fileEl获取到文件信息是有延迟的,因此这里补充timeout和判断文件长度来确保logic OK
  3. 之所以onclick时进行赋空值处理,是因为如果还是选择同一个文件onchange并不会触发,如果没有此需求可以去掉

官方论坛

官方论坛有该需求的讨论,至少目前还未支持

https://www.w3.org/Bugs/Public/show_bug.cgi?id=25452