dragover事件必须调用event.preventDefault()才能启用自定义拖拽上传,否则drop事件不会触发;获取文件应使用dataTransfer.files而非items或types;校验文件需检查大小和扩展名;多文件上传推荐多次append到FormData。

dragover 事件必须阻止默认行为,否则拖拽会失效
浏览器对文件拖拽有默认处理逻辑:把文件拖进页面时,会直接打开或下载。要启用自定义上传,dragover 事件里必须调用 event.preventDefault(),否则后续的 drop 根本不会触发。
-
dragenter和dragover都要监听,但只有dragover的preventDefault()是强制必需的 - 不要只在
drop里阻止默认行为——那时已经晚了 - 如果用了第三方 UI 库(如 Element Plus、Ant Design),检查其
upload组件是否已封装好这层逻辑;没封装的话需手动补上
从 DataTransfer 获取文件要用 files 属性,不是 items 或 types
event.dataTransfer 看似有多个属性可选,但真正稳定读取用户拖入的文件列表,唯一可靠的是 files 属性。它返回一个 FileList,和 的 files 完全一致。
-
items是实验性 API,部分浏览器(如 Safari)不支持getAsFile(),且类型判断复杂 -
types只是 MIME 类型数组,不能用来读文件内容 - 直接遍历
event.dataTransfer.files即可,例如:const files = event.dataTransfer.files; for (let i = 0; i < files.length; i++) { const file = files[i]; console.log(file.name, file.size, file.type); }
拖拽区域需要显式设置 dropzone 属性或 CSS 兼容性兜底
虽然现代浏览器不强制要求 dropzone 属性,但某些旧版 Chrome 或 Electron 环境下,仅靠 JS 监听不够。更稳妥的做法是:给目标容器加 dropzone="copy",并确保它有明确宽高和背景(否则可能点不中、拖不进)。
-
dropzone值只能是copy、move或link,上传场景一律用copy - 若用
display: flex或position: absolute布局,注意父容器不能是overflow: hidden,否则拖拽阴影显示异常 - 移动端不支持原生拖拽,这个方案仅适用于桌面端
上传前建议校验 size 和 type,避免后端拒绝又无提示
前端拦截明显违规文件能减少无效请求。但注意:MIME 类型可伪造,file.type 仅作参考;真正可靠的校验必须由后端做,前端只是提升体验。
立即学习“前端免费学习笔记(深入)”;
- 检查大小:
if (file.size > 10 * 1024 * 1024) { /* 超过 10MB */ } - 检查扩展名比 MIME 更直观:
const ext = file.name.split('.').pop().toLowerCase(); if (!['jpg', 'png', 'pdf'].includes(ext)) { ... } - 多个文件批量上传时,建议用
FormData.append('files', file)多次追加,而非合并成一个 Blob
拖拽上传本身逻辑简单,真正容易出问题的是事件生命周期理解偏差和跨浏览器行为差异。特别是 Safari 对 dataTransfer.items 的限制、IE 完全不支持,以及 Electron 中 WebContents 的 drag-drop 权限配置——这些不在标准 HTML5 范围内,但实际项目里常踩坑。











