likes
comments
collection
share

一文搞懂文件夹拖动上传到浏览器的实现

作者站长头像
站长
· 阅读数 12

相信你一定经常遇见过下面的场景🌚

🥰嘿嘿,给好兄弟分享点快乐资源

一文搞懂文件夹拖动上传到浏览器的实现 😫为什么阻止我分享快乐,每次都得打包才发送,麻烦死了。

不行我要自己弄一个,让大家都能快乐分享。

我的思路

既然要用文件夹分享给对方,我们就得简单了解下文件夹是什么。

文件夹是一种用于组织和存储文件的容器,它本身不是一种文件,但在计算机系统中被视为一种特殊类型的文件

也就是说我们实际上是不能直接传递文件夹的,因为文件夹只是为了方便我们查看文件的路径而存在的,并不是真实的文件

动手实践🙌

方式一:直接发送多个文件

思路:

  • 拖动文件夹到浏览器
  • 浏览器获取文件夹里的每个文件
  • 将获取到的文件发送请求给对方
1:让我们的上传区域可放置

首先我们给拖动区域添加两个响应事件dragoverdrop,这样这个区域就能获取到拖动文件。(如果不熟悉可以到我写的另一篇文章中熟悉一下拖拽事件)

<div class="dropzone">
    将文件拖到这里
</div>

const dropzone = document.querySelector('.dropzone');

dropzone.addEventListener('dragover', (event) => {

    event.preventDefault(); //阻止默认行为,允许放置

});

dropzone.addEventListener('drop', (event) => {

    event.preventDefault(); //阻止浏览器默认行为,不会自动打开文件管理页面
    const DataTransferItemList = event.dataTransfer.items; // 获取文件的数据
    console.log(DataTransferItemList); // 打印看看
    
});

一文搞懂文件夹拖动上传到浏览器的实现

2:获取文件夹里的数据

这时候就要有请我们的老朋友DataTransfer拖动对象了,看看它能为我们提供什么数据:

  • DataTransfer.files :包含数据传输中可用的所有本地文件的列表。如果拖动操作不涉及拖动文件,则此属性为空列表。

一文搞懂文件夹拖动上传到浏览器的实现

DataTransfer对象用于保存拖动并放下的数据,我们希望能得到文件夹的的所有文件,你可能会想要使用DataTransfer.files,不过很遗憾它只包含我们拖动时的文件,并不能获取到内部的文件,所以我们选择使用DataTransfer.items来获取我们的文件。

3:🔧DataTransfer.items的处理

一文搞懂文件夹拖动上传到浏览器的实现

DataTransfer.items返回DataTransferItemList对象是一组拖动列表,里面的每个拖动项DataTransferItem就表示我们拖动的文件。 比如你拖动两个文件夹或两个文件到浏览器,那么列表就有两个DataTransferItem对象。

一文搞懂文件夹拖动上传到浏览器的实现

所以我们的重点是处理DataTransferItem对象。

具体流程:

1:使用DataTransferItem.webkitGetAsEntry()方法(非标准),获取文件夹对应文件系统的实体对象。

dropzone.addEventListener('drop', (event) => {

    event.preventDefault();

    const dataTransferItemList = event.dataTransfer.items // 获取文件的数据

    for(const dataTransferItem of dataTransferItemList) {

        const file = dataTransferItem.webkitGetAsEntry();
        console.log(file);

    }

});

一文搞懂文件夹拖动上传到浏览器的实现

打印一下可以看到里面有一个属性isFile,用来判断是文件夹还是文件类型,会作为我们的一个判断条件。

2:编写文件夹处理函数handlefile(file)

function handlefile(file) {

    const dirReader = file.createReader()

    dirReader.readEntries(function(entries) {

    console.log(entries);

})

}

const dirReader = file.createReader(): 这里创建了一个文件夹读取器 dirReader,用于读取指定文件夹 file 中的内容。

dirReader.readEntries(function(entries) { ... }): 这是异步方法,它读取文件夹中的所有文件和子文件夹,并在读取完成后执行回调函数。回调函数中的 entries 是一个包含文件夹中文件和子文件夹的数组。

一文搞懂文件夹拖动上传到浏览器的实现 经过不懈努力,我们终于得到想要的entries🥳

因为文件夹中可能还有文件夹,所以我们需要对文件夹里的文件夹也进行递归处理。

让我们完善一下代码

function handlefile(file) {
    if (file.isFile) {
        // 是文件执行上传操作
        //file.file() 方法用于读取文件内容
        file.file(function(f) {
            // f才是最终的文件
            console.log(f);
            const text = document.createTextNode(f.name+'—');
            dropzone.appendChild(text);
            return
        })
    } else {
        // 是文件夹,读取文件夹里的文件,遍历文件夹
        const dirReader = file.createReader()
        dirReader.readEntries(function(entries) {
            // 遍历entries,对文件进行处理
            for (let i = 0; i < entries.length; i++) {
                handlefile(entries[i])
            }
        })
   }

}

最终效果:

一文搞懂文件夹拖动上传到浏览器的实现

我们获得最后的f就是我们需要的文件,只需要将这个f文件通过网络请求发送给对方就行了。

方式二:压缩上传(思路)

相信以你聪明的脑瓜,一定发现了这种方式的弊端,要是我们发送的文件夹有100个文件,那就要发起100个请求,这会增加网络通信的开销,可能会导致网络拥塞和传输延迟。

所以把文件夹打包成压缩包再发送是最高效的,当然考虑到我很懒,不想自己压缩打包,那就把这个活交给我们的浏览器干就好了。 可以看看使用JSZip等库来帮助我们,这里就提供思路了,具体操作小伙伴们自行探索。

完整代码:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Document</title>

<style>

.dropzone {

width: 300px;

height: 300px;

background-color: aquamarine;

}

</style>

</head>

<body>

<div class="dropzone">

将文件拖到这里:

</div>

<script>

const dropzone = document.querySelector('.dropzone');

  


function handlefile(file) {

if (file.isFile) {

// 是文件执行上传操作

//file.file() 方法用于读取文件内容

file.file(function(f) {

// f才是最终的文件

console.log(f);

const text = document.createTextNode(f.name+'—');

dropzone.appendChild(text);

return

})

} else {

// 是文件夹,读取文件夹里的文件,遍历文件夹

const dirReader = file.createReader()

dirReader.readEntries(function(entries) {

// 遍历entries,对文件进行处理

for (let i = 0; i < entries.length; i++) {

handlefile(entries[i])

}

})

}

}

  


dropzone.addEventListener('dragover', (event) => {

  


event.preventDefault(); //阻止默认行为,允许放置

  


});

  


dropzone.addEventListener('drop', (event) => {

event.preventDefault();

const dataTransferItemList = event.dataTransfer.items // 获取文件的数据

for(const dataTransferItem of dataTransferItemList) {

const file = dataTransferItem.webkitGetAsEntry();

handlefile(file);

}

});

</script>

</body>

</html>
转载自:https://juejin.cn/post/7258145453207715897
评论
请登录