js拖拽文件夹上传文件(附较完整注释)

发布: 2021-06-02 17:25:36 标签: js基础

scanFiles.js 通过drop事件获取文件夹中

经测试兼容新版chrome和safari浏览器。注意:chrome 每次只能读取100个文件,所以下边代码循环读取。

01// 仅支持选择一个文件夹,并且不会递归上传
02async function scanFiles(e) {
03 e.preventDefault()
04 const { items = [], files = [] } = e.dataTransfer
05
06 // 只上传第一个文件夹
07 const [item] = items
08 if (!item || !item.webkitGetAsEntry) return files
09
10 // 如果是文件直接返回文件
11 const entry = item.webkitGetAsEntry()
12 // 第一个类目是文件直接返回files,如果是文件夹下则返回第一层目录
13 return entry.isFile ? files : getEntryDirectoryFiles(entry)
14}
15
16// 获取文件夹中文件
17function getEntryDirectoryFiles(entry) {
18 const reader = entry.createReader()
19 // 一次最多只能读100,防止出现文件夹内文件个数过多,加一个变量收集最新的结果
20 let res = []
21 return read()
22
23 async function read() {
24 const files = await new Promise((resolve, reject) =>
25 reader.readEntries((entries) => {
26 // 只上传一层文件,过滤文件夹中包含的文件夹
27 const fileEntries = entries.filter((entry) => entry.isFile)
28 const filesPromise = fileEntries.map((entry) => new Promise((resolve) => entry.file((file) => resolve(file))))
29 Promise.all(filesPromise).then(resolve)
30 }, reject)
31 )
32 // 保存当前读取文件
33 res = [...res, ...files]
34 // chrome浏览器一次读取最多获取100个文件,多于100个需要再次读取
35 if (files.length < 100) {
36 return res
37 }
38 return read()
39 }
40}
41
复制代码

拖拽文件夹上传测试

01// 阻止浏览器打开新标签,ondrop/ondragover/ondragenter(最好加上这个防兼容问题)
02window.ondragover = (e) => e.preventDefault()
03
04// 获取文件夹
05window.ondrop = async (e) => {
06 const files = await scanFiles(e)
07 console.log('获取到文件', files)
08}
复制代码