首页 > 建站教程 > JS、jQ、TS >  js拖拽文件夹,得到文件夹内的所有文件正文

js拖拽文件夹,得到文件夹内的所有文件

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
}