拖拽上传必须监听dragover(需preventDefault)、drop和可选dragenter/dragleave;dragover不阻止默认行为则drop不触发,drop中通过dataTransfer.files获取文件,用FileReader或URL.createObjectURL预览,校验type和size后以FormData正确append上传。

拖拽区域监听哪些事件才真正有效
拖拽上传不是监听 dragstart 就完事——那是拖出方的事,而上传需要的是目标区域(比如一个 div)响应“被拖进来”和“松手放下”的过程。真正必须绑定的只有三个:dragover、drop 和可选的 dragenter/dragleave(用于视觉反馈)。其中 dragover 必须调用 event.preventDefault(),否则浏览器会走默认行为(打开文件、导航跳转等),drop 才能触发。
常见错误:只加了 drop 但没阻止 dragover,结果松手后页面跳转或啥也不发生。
-
dragover:必须调用event.preventDefault(),否则drop不触发 -
drop:从event.dataTransfer.files取FileList,这才是用户拖进来的文件 -
dragenter和dragleave:仅用于添加/移除hover类,不影响功能逻辑
如何安全读取拖入的文件并预览
拖入的 File 对象不能直接发请求,得先用 FileReader 处理(比如读成 base64 预览图片),或构造 FormData 上传。注意:不是所有文件都适合预览,file.type 和 file.name 要校验,避免用户拖来 .exe 或超大日志文件卡死页面。
示例中常漏掉 MIME 类型判断,导致 image/* 检查写成 file.type === 'image/jpeg',漏掉 png/webp;更稳妥是用 file.type.startsWith('image/')。
立即学习“前端免费学习笔记(深入)”;
- 用
URL.createObjectURL(file)快速生成本地预览链接(比 base64 轻量,适合大图) - 上传前建议检查
file.size,比如限制 ≤20MB:if (file.size > 20 * 1024 * 1024) - 多个文件时,
event.dataTransfer.files是只读FileList,需转为数组才能用map:Array.from(event.dataTransfer.files)
为什么 drop 后页面有时会自动跳转到文件地址
这是最典型的未拦截导致的副作用:浏览器对拖入的文件(尤其是图片、文本)有默认处理逻辑,drop 事件本身不阻止它,只要 dragover 没调 preventDefault,松手瞬间就会导航到该文件 URI(表现为页面变白、显示图片或下载弹窗)。
调试技巧:在 dragover 回调里加个 console.log('over'),拖进去没输出?说明事件根本没绑定上,或者父元素捕获了事件没冒泡下来。
- 确保监听的是实际接收拖拽的容器元素,不是
document或body(除非你真想全局支持) - 如果用了框架(如 Vue/React),别把事件绑在虚拟节点上,要确保 ref 拿到真实 DOM 并调用
addEventListener - 移动端不支持原生 drag/drop,这个功能在 iOS/Android 浏览器里默认不可用
上传逻辑怎么接后端才不丢文件名和类型
直接把 File 对象 append 到 FormData 即可,浏览器会自动带上 name 和 type 字段。但要注意:如果后端要求字段名不是 file,比如叫 upload,那 formData.append('upload', file) 才对;若错写成 formData.append('file', file.name),就只传了字符串,后端收不到二进制流。
另外,fetch 发送时不要手动设 Content-Type,让浏览器自动生成带 boundary 的 multipart/form-data 头,否则后端解析失败。
- 正确:
formData.append('file', file)—— 传整个 File 对象 - 错误:
formData.append('file', file.name)或formData.append('file', file.path)(file.path在浏览器中根本不存在) - 上传时用
fetch('/upload', { method: 'POST', body: formData }),不设headers['Content-Type']
拖拽上传看着简单,但 dragover.preventDefault() 这一行漏掉,整个流程就断在第一步;文件对象的边界处理(大小、类型、多选)、以及 FormData 的 append 方式,都是上线后容易突然报错的点。



















