使用ev.preventDefault()阻止文件上传后,如何显示拖拽文件名?
解决拖拽文件到input后阻止默认上传同时显示文件名的问题
问题核心:使用ev.preventDefault()阻止拖拽文件的默认上传行为后,input组件无法自动显示拖拽的文件名——因为浏览器默认的文件关联逻辑被中断了,需要手动将拖拽的文件绑定到input元素上。
解决方案
在dropHandler函数中,完成文件获取后,手动创建DataTransfer对象并将文件赋值给input的files属性,同时必须调用ev.preventDefault()阻止默认行为:
修改后的JavaScript代码:
let uploadedCSVfile; const drop_zone = document.getElementById('drop_zone'); const csv_file_input = document.getElementById('csv_file'); function dropHandler(ev) { console.log('File(s) dropped'); // 必须阻止默认行为,防止页面跳转或打开文件 ev.preventDefault(); let files = []; if (ev.dataTransfer.items) { // 处理DataTransferItemList接口 for (var i = 0; i < ev.dataTransfer.items.length; i++) { if (ev.dataTransfer.items[i].kind === 'file') { var file = ev.dataTransfer.items[i].getAsFile(); console.log('DTIL... file[' + i + '].name = ' + file.name); files.push(file); uploadedCSVfile = file; } } } else { // 处理DataTransfer接口 files = Array.from(ev.dataTransfer.files); for (var i = 0; i < files.length; i++) { console.log('DT... file[' + i + '].name = ' + files[i].name); } if(files.length > 0) uploadedCSVfile = files[0]; } // 手动将文件绑定到input元素,使其显示文件名 if(files.length > 0) { const dataTransfer = new DataTransfer(); files.forEach(file => dataTransfer.items.add(file)); csv_file_input.files = dataTransfer.files; } } function dragOverHandler(ev) { ev.preventDefault(); drop_zone.style.border = "3px dotted red"; } function dragLeave(event) { if (event.target.id == "drop_zone") { event.target.style.backgroundColor = ""; drop_zone.style.border = "2px dotted black"; } }
HTML代码保持不变:
<div id="drop_zone" ondrop="dropHandler(event);" ondragover="dragOverHandler(event);" ondragleave="dragLeave(event); "> <form id="prod_csv_upload" style="margin-top: 10px;"> <label for="csv_file"> <!-- this input actually receives the file --> <input type="file" id="csv_file" accept=".csv" /><br> </label> </form> </div>
关键说明
ev.preventDefault()必须在dropHandler中调用,否则浏览器会执行打开文件/跳转的默认行为- 由于input的
files属性是只读的,不能直接赋值数组,必须通过DataTransfer对象来构造文件列表再赋值,这样才能触发input的文件名显示逻辑 - 代码兼容了
DataTransferItemList和DataTransfer两种接口,覆盖不同浏览器的支持情况
内容的提问来源于stack exchange,提问作者OosoO
相关产品推荐
相关产品推荐

