vue对文件夹进行拖拽上传完整流程(文件夹中超出100个文件)

前言

上个文章介绍了多图片压缩,多图片可以通过直接多选图片进行拖拽,也可以通过直接拖拽文件夹进行解析得到多图片,接下来直接上代码

先展示文件拖拽后对文件的解析效果

图片文件夹

在这里插入图片描述

图片文件夹解析

在这里插入图片描述

大文件夹(包含280个文件)上传

在这里插入图片描述

280个文件解析

![在这里插入图片描述](https://img-blog.csdnimg.cn/8985bda3ac5a4c9da6ad79e62fceb9fd.png#pic_center
在这里插入图片描述

// 这里是template中代码
<div
 class="middle-ccc"
   :class="[{ 'drop-shadow': dropType === 'ccc' }]"
   @dragenter.stop.prevent="handlePictureBoxDragenter('ccc')"
   @dragover.stop.prevent=""
   @dragleave.stop.prevent="handlePictureBoxDragleave"
   @drop.stop.prevent="handlePictureBoxDrop($event, 'ccc')"
>
	// 内部代码省略
 </div>

// 这里是vue3的js处理流程
const fileArrPromiseResolve = ref(null) // 图片文件上传的promise事件
const fileArrPromise = ref(null)

// 设置文件加载的promise
const initFileArrPromise = () => {
    fileArrPromise.value = new Promise((resolve) => {
        fileArrPromiseResolve.value = resolve
    })
}

// 文件拖拽dragenter进入
const handlePictureBoxDragenter = (type) => {
	// 这里传入一个10ms的延迟锁,让dragleave在enter延迟后触发
    pictureBoxLock.value = true
    setTimeout(() => {
        pictureBoxLock.value = false
    }, 10)
    // dropType.value是文件拖拽进选中范围的高亮效果
    dropType.value = type
}

// 文件拖拽dragleave离开
const handlePictureBoxDragleave = () => {
    // 多张图片拖拽进入的延迟锁时返回
    if (pictureBoxLock.value) return
    dropType.value = ''
}

// 文件拖拽drop落下
const handlePictureBoxDrop = async (e) => {
    dropType.value = ''
    // 判断file是文件夹还是文件
    const isDirectory = e.dataTransfer.items[0].webkitGetAsEntry().isDirectory
    // 这里的file给了一个初始值,如果是单张或多张图片拖拽可以直接获取其files属性
    let file = e.dataTransfer.files
    if (isDirectory) {
    	// 这里对promise进行一个初始化
        initFileArrPromise()
        // 这里获取到文件的一个file信息
        const fileItems = e.dataTransfer.items[0].webkitGetAsEntry()
        // 这里是对fileItems处理,返回的是所有文件的数组
        file = await getFileDirectory(fileItems)
    }
    // 如果未能读取到想要的图片或者文件夹为空,都直接提示错误返回
    if (!file || !file.length) {
        ElMessage({ message: '图片上传错误', type: 'error' })
        return
    }
    console.log(file, 'file)
}

// 这里对文件处理通过promise进行处理,为了确保文件夹中最后一个文件读取完成后再进行操作
const getFileDirectory = (fileItems) => {
    return new Promise((resolve) => {
        fileTypeLoop(fileItems, '', [])
        fileArrPromise.value.then((file) => {
            resolve(file)
        })
    })
}
//	TODO: 这段代码过于复杂,后面会考虑优化
// 文件夹上传解析,进行了递归和类型划分,返回fileArr数组
const fileTypeLoop = (fileItem, path, fileArr, loopOver = false) => {
    let dirReader = null
    // 如果fileItem是文件而不是文件夹进入
    if (fileItem.isFile) {
        fileItem.file((file) => {
        	// fileTypeFilter方法是对你想要哪一类型的文件,我这里只想要图片格式
            const fileFilter = file.type && 'image/gif,image/jpeg,image/jpg,image/png,image/bmp'.indexOf(file.type) > -1
            if (fileFilter) {
            	// 这里将路径重新进行整理
                fileItem.path = path + file.name
                // 重新创建file数据格式,加入type和path放入到fileArr中
                const newFile = new File([file], fileItem.path, { type: file.type })
                fileArr.push(newFile)
            }
            // 如果文件夹读到最后一个时,将fileArr数组通过resolve返回出去
            if (loopOver) fileArrPromiseResolve.value(fileArr)
        })
    } else if (fileItem.isDirectory) {	// 如果fileItem是文件夹,读取文件夹内容再进行处理
        dirReader = fileItem.createReader()
        dirReader.readEntries(onReadEntries)
    }
    // 通过递归解析出文件夹中所有文件,readEntries正常只能读出100个文件
    // 项目中一个文件中有280个文件,能成功读取出
    function onReadEntries(entries) {
        for (let i = 0; i < entries.length; i++) {
        	// 判断是否是最后一个文件,是的话就让loopOver为true
            if (i === entries.length - 1 && !entries[i].isDirectory && entries.length < 100) loopOver = true
            // 进行递归处理
            fileTypeLoop(entries[i], path, fileArr, loopOver)
        }
        // 如果entries.length则说明文件中可能不止100个文件,这个时候需要继续嵌套读取
        if (entries.length) dirReader.readEntries(onReadEntries)
    }
}



// 这里是style样式
.drop-shadow {
     box-shadow: 0px 0px 12px #18bae3;
 }

上述API的描述文档

webkitGetAsEntry:如果DataTransferItem描述的项目是一个文件,webkitGetAsEntry()返回一个表示它的FileSystemFileEntry或FileSystemDirectoryEntry。如果项目不是文件,则返回null

createReader:FileSystemDirectoryEntry接口的方法createReader()返回一个
FileSystemDirectoryReader对象,可用于读取目录中的条目

readEntries:FileSystemDirectoryReader接口的readEntries()方法检索正在读取的目录中的目录条目,并将它们以数组的形式传递给所提供的回调函数

e.dataTransfer:该DataTransfer对象用于保存在拖放操作期间被拖动的数据。它可以保存一个或多个数据项,每个数据项是一种或多种数据类型
具体参数:
(1)dataTransfer.dropEffect:获取当前选择的拖放操作的类型或将操作设置为新类型。该值必须是none、copy
(2)dataTransfer.effectAllowed
:提供所有可能的操作类型。必须是none, copy, copyLink, copyMove, link, linkMove, move,all
(3)dataTransfer.files
:包含数据传输中可用的所有本地文件的列表。如果拖动操作不涉及拖动文件,则该属性为空列表
(4)dataTransfer.items (只读)
:给出一个DataTransferItemList对象,它是所有拖动数据的列表
(5)dataTransfer.types (只读)
:dragstart一个字符串数组,给出在事件中设置的格式

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值