js要实现拖拽文件夹到页面,得到此文件夹内所有文件。如果是选择文件夹简单,在input:file中,有一个属性,用于控制在点击上传文件按钮时,用于展示文件还是文件夹的属性,这个属性就是webkitdirectory,详见 webkitdirectory 文件夹上传功能
今天要实现的不是点击选择文件夹,而是拖拽文件夹,得到里面的文件:
假设有个div:
<div @dragenter.stop.prevent @dragover.stop.prevent @drop.stop.prevent="ondrop($event)">将文件夹拖拽到此处进行上传</div>
其中:dragenter、dragover、drop都是H5新增的拖放api,它们默认会触发一些默认事件,这里将它阻止了,然后在ondrop时,写获取文件夹内文件的方法。如果拖放的是一个文件 去读取e.dataTransfer.files就可以了:
function ondrop(e) { if(props.disabled) return var files = []; [].forEach.call(e.dataTransfer.files, function(file) { files.push(file); },false); // 这个 files,就是拖拽的文件,可能是多个 }
但是如果是一个文件夹就不能拿这个属性里面的值了,因为此时你拿到的是一个文件夹的信息,而不是你希望拿到的文件夹内部所有文件的信息。此时,我们需要去拿的是e.dataTransfer.items 这个属性,但是需要注意的是,这个属性也不是直接可以拿来用的,需要另外的方法,将文件夹里面的属性读取之后,才能够使用。重写上面的 ondrop 方法:
function ondrop(e) { dealWithFolders(e.dataTransfer.items) } function dealWithFolders(items) { if (items.length > 1) { ElMessage({ message: '一次只允许上传一个文件夹', type: 'error', }) return } var item = items[0].webkitGetAsEntry() if (item) { checkFolders(item) } } // 判断是否为文件夹 function checkFolders(item) { if (item.isDirectory) { let result = traverseFileTree(item) // 这个result 就是最终文件夹内所有的文件。 } else { ElMessage({ message: '只支持上传文件夹', type: 'error', }) } } function traverseFileTree(item) { let res = [] var internalProces = (item, path, res) => { if (item.isFile) { item.file(file => { file.path = path + file.name var newFile = new File([file], file.path, { type: file.type }) res.push(newFile) }) } else if (item.isDirectory) { var dirReader = item.createReader() dirReader.readEntries( entries => { for (let i = 0; i < entries.length; i++) { internalProces(entries[i], path + item.name + "/", res) } }, function(e) { console.log(e) } ) } } internalProces(item, "", res) return res }