流程
- 通过drop事件获取用户拖拽的文件
- 如果是文件,执行上传
- 如果是目录,递归目录下所有的文件,执行上传
代码
<template>
<div
@dragover.prevent
@dragenter.prevent
@dragleave.prevent
@drop.prevent="handleDrop"
>拖拽区域</div>
</template>
<script setup lang="ts">
const uploadFiles = () => {}
// TODO: 这里的directory需要声明一下类型
const traverseDirectory = async (directory) => {
const fileList: File[] = []
const reader = directory.createReader()
const readEntriesSync = reader => new Promise<FileSystemFileEntry[]>((resolve, reject) => {
reader.readEntries(resolve, reject)
})
const entries = await readEntriesSync(reader)
for (const entry of entries) {
if (entry.isFile) {
const file: File = await new Promise((resolve, reject) => {
entry.file(resolve, reject)
})
Object.defineProperty(file, 'webkitRelativePath', {
value: entry.fullPath,
})
fileList.push(file)
return
}
if (entry.isDirectory) {
const subFiles = await traverseDirectory(entry)
fileList.push(...subFiles)
return
}
}
return fileList
}
// TODO: 这里的data需要声明一下类型
const upload = async (data) => {
// TODO: 这里的entry需要声明一下类型
const entry = data.webkitGetAsEntry()
if (entry?.isFile) {
// 获取文件对象
const file = data.getAsFile()
if (file !== null) {
uploadFiles([file])
}
} else {
// 递归获取目录下所有的文件对象
const files = await traverseDirectory(entry)
uploadFiles(files)
}
}
const handleDrop = async (event: DragEvent) => {
if (event.dataTransfer === null) {
return
}
const items = event.dataTransfer.items
for (const item of items) {
await upload(item)
}
}
</script>
为什么不直接用event.dataTransfer.files?
event.dataTransfer.files 是一个 FileList 对象,包含了拖放事件中所有文件的列表。它非常适合处理单个或多个文件的上传。
但是,如果用户拖放的是一个文件夹,event.dataTransfer.files 只会获取文件夹中的文件,无法用来递归地获取子文件夹中的文件和子文件夹。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。