4

流程

  1. 通过drop事件获取用户拖拽的文件
  2. 如果是文件,执行上传
  3. 如果是目录,递归目录下所有的文件,执行上传

代码

<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 只会获取文件夹中的文件,无法用来递归地获取子文件夹中的文件和子文件夹。


热饭班长
3.7k 声望434 粉丝

先去做,做出一坨狗屎,再改进。


下一篇 »
问题备忘

引用和评论

0 条评论