在 drop 事件中通过 event.dataTransfer.files 获取 FileList,需同时阻止 dragover 和 drop 的默认行为;File 可直接传 FormData 上传,校验应基于 file.type 而非后缀; FileReader onload 中 this 指向 reader 实例,推荐用 event.target.result;iOS Safari 不支持文件拖放,须降级为 input[type=file]。

drop 事件里怎么拿到拖进来的文件
直接从 event.dataTransfer.files 读,它是个 FileList 对象,不是数组但可用 [...files] 展开。别去碰 event.dataTransfer.items——除非你要处理目录或非文件项,否则纯属增加复杂度。
常见错误是监听了 dragover 却没调 event.preventDefault(),导致浏览器默认行为拦截了 drop;或者只监听了 drop 但没同时阻止 dragover 的默认行为,结果 drop 根本不触发。
- 必须在
dragover和drop两个事件里都调用event.preventDefault() -
event.dataTransfer.files在drop时才有效,dragenter/dragover里为空 - 如果用户拖的是文件夹(Chrome/Firefox 支持),
files里只包含文件,不包含子目录结构
File 对象怎么读内容并上传
File 是 Blob 的子类,所以能直接传给 FormData 或 fetch。不需要先转成 base64 或 ArrayBuffer——除非你得预览图片或校验 hash。
上传前建议加基础校验:文件大小、类型。比如限制只接受 image/*,就检查 file.type.startsWith('image/'),别只靠后缀名(file.name)判断,容易被绕过。
立即学习“前端免费学习笔记(深入)”;
const handleDrop = (event) => {
event.preventDefault();
const files = event.dataTransfer.files;
for (let file of files) {
if (file.size > 10 * 1024 * 1024) {
console.warn(`${file.name} 超过 10MB,跳过`);
continue;
}
const formData = new FormData();
formData.append('file', file); // 注意字段名要和后端约定一致
fetch('/upload', { method: 'POST', body: formData });
}
};为什么 FileReader onload 里 this 指向不对
因为 FileReader 的事件回调里 this 指向 reader 实例,不是外层作用域。写法上要么用箭头函数,要么提前存 const that = this,但更推荐直接用 event.target.result——这是最稳的取值方式。
另一个坑是:readAsDataURL 会把大文件撑爆内存,上传前预览小图建议用 createObjectURL,它返回 blob URL,不读全文,也不触发 GC 压力。
-
reader.onload = function() { console.log(this.result); }✅ -
reader.onload = () => { console.log(this.result); }❌(this 是外层作用域,不是 reader) - 大文件慎用
readAsDataURL,优先选URL.createObjectURL(file)
移动端 Safari 对拖放的支持情况
iOS Safari 完全不支持 drag & drop API 拖文件——连 drop 事件都不会触发。别浪费时间适配,老老实实 fallback 到 。
Android Chrome 支持,但仅限于从文件管理器拖进网页;微信内置浏览器、QQ 浏览器等 WebView 大多不支持,或只支持点击触发文件选择。
检测是否可用:尝试监听 dragover 并看能否触发,但更可靠的是 UA + 特性检测组合:
const supportsDnD = 'draggable' in document.createElement('span') &&
'ondrop' in document.createElement('div');不过这只能说明 DOM 层支持,不能保证文件拖放可用。真要健壮,还是得服务端兜底 + 客户端降级提示。
拖放上传看着高级,但实际落地时,兼容性、错误反馈、大文件中断续传、进度条这些才是卡点。别一上来就堆 API,先把 input[type=file] 的体验做扎实,再考虑加拖放糖衣。










