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
}