取消文件上传需中断 fetch 或 XMLHttpRequest 请求,而非清空 input.value;fetch 用 AbortController.signal 实现,XHR 用 abort() 方法;同时须同步按钮状态并清理 Blob 和预览 URL 等资源。

取消 <input type="file"> 的上传行为本身不可行
HTML 原生 <input type="file"> 元素没有“上传”能力,它只负责选择文件。真正触发上传的是你后续用 fetch、XMLHttpRequest 或第三方库(如 axios)发起的网络请求。所以「取消上传」实际是取消那个正在执行的请求,不是清空 input。
常见误解是调用 input.value = '' —— 这只会清空已选文件显示,对正在进行的上传毫无影响。
用 AbortController 取消 fetch 上传
现代浏览器中,fetch 支持通过 signal 参数接入取消机制。这是最直接、标准的做法。
- 创建
AbortController实例,在上传前保存其signal - 将
signal传入fetch()的options中 - 点击「取消」时调用
controller.abort() -
fetch会立即 reject,错误类型为DOMException,name === 'AbortError'
let controller = null;
function startUpload(file) {
controller = new AbortController();
const formData = new FormData();
formData.append('file', file);
fetch('/upload', {
method: 'POST',
body: formData,
signal: controller.signal // 关键
})
.catch(err => {
if (err.name === 'AbortError') {
console.log('上传已取消');
} else {
console.error('上传失败', err);
}
});
}
function cancelUpload() {
if (controller) controller.abort();
}
XMLHttpRequest 的 abort() 更早但需手动处理状态
如果你还在用 XMLHttpRequest(比如兼容旧项目),它的 .abort() 方法是同步生效的,但要注意:调用后仍会触发 onloadend 或 onreadystatechange,需在回调里检查 xhr.readyState === 0 或 status === 0 来区分是取消还是失败。
立即学习“前端免费学习笔记(深入)”;
-
xhr.upload.onprogress在abort()后不会再触发 - 务必在调用
abort()前确保xhr不为null且处于发送状态 - 不要依赖
onerror判断取消——它不会被触发
UI 层要同步禁用/还原按钮状态
取消操作不只是中断请求,还要避免用户重复点击或误操作:
- 开始上传时,禁用「上传」按钮,启用「取消」按钮
- 调用
abort()后,恢复「上传」按钮,禁用「取消」按钮 - 上传成功或失败(非取消)后,也要重置按钮状态
- 如果使用
disabled属性,记得同时用aria-disabled保证可访问性
漏掉状态同步,用户可能点两次取消、或上传结束后还能点取消——后者虽无害,但体验割裂。
真正容易被忽略的是 abort 后的资源清理:比如大文件的 Blob 引用、预览 URL(用 URL.revokeObjectURL)、以及是否要清空 input 的视觉状态(input.value = '' 是安全的,仅影响 UI,不干扰已发出的请求)。



















