流程
- 通過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 只會獲取文件夾中的文件,無法用來遞歸地獲取子文件夾中的文件和子文件夾。