当前位置: 首页 > backend >正文

vue文件或文件夹拖拽上传

一、示例

二、组件代码

<template><divclass="drop-area":class="{ dragging: isDragging }"@dragover.prevent="handleDragOver"@dragleave="handleDragLeave"@drop.prevent="handleDrop"><el-icon class="el-icon--upload"><upload-filled /></el-icon><p>拖拽文件或文件夹到此处,开始上传</p><!-- <p v-if="fileList.length">已选择 {{ fileList.length }} 个文件</p> --></div>
</template><script setup>import { ref, defineEmits } from 'vue'const emits = defineEmits(['change'])// 响应式状态const isDragging = ref(false)const fileList = ref([])// 处理拖拽进入const handleDragOver = (e) => {isDragging.value = truee.dataTransfer.dropEffect = 'copy'}// 处理拖拽离开const handleDragLeave = () => {isDragging.value = false}// 处理文件放置const handleDrop = async (e) => {isDragging.value = falseconst droppedFiles = await extractFilesFromDropEvent(e)fileList.value = [...droppedFiles]console.log(droppedFiles, 123)emits('change', droppedFiles)}// 从拖拽事件中提取所有文件const extractFilesFromDropEvent = async (event) => {const items = event.dataTransfer.itemsconsole.log('拖拽项数量:', items?.length)if (!items) return []// 使用Promise.all并行处理所有文件项const promises = Array.from(items).map(async (item) => {if (item.kind === 'file') {const entry = item.webkitGetAsEntry()if (entry) {console.log('正在处理文件:', entry)// 递归处理文件条目const fileResult = await traverseFileEntry(entry, '')return fileResult}}return null})// 等待所有处理完成并合并结果const results = await Promise.all(promises)// 扁平化结果数组并过滤掉null值return results.flat().filter(Boolean)}// 递归遍历文件系统条目const traverseFileEntry = (entry, relativePath) => {return new Promise((resolve) => {if (entry.isFile) {// 处理文件entry.file((file) => {// 添加相对路径信息file.relativePath = relativePath ? `${relativePath}/${file.name}` : ''resolve(file)})} else if (entry.isDirectory) {// 处理目录const dirReader = entry.createReader()dirReader.readEntries(async (entries) => {const subPath = relativePath? `${relativePath}/${entry.name}`: entry.name// 对目录项使用Promise.all并行处理const promises = Array.from(entries).map((subEntry) =>traverseFileEntry(subEntry, subPath))const results = await Promise.all(promises)// 扁平化目录下的所有文件resolve(results.flat().filter(Boolean))})} else {resolve(null)}})}
</script><style scoped>.drop-area {width: 100%;min-height: 100px;border: 2px dashed #ccc;border-radius: 8px;display: flex;flex-direction: column;align-items: center;justify-content: center;padding: 20px;transition: all 0.3s ease;margin: 0px;}.drop-area.dragging {border-color: #409eff;background-color: rgba(64, 158, 255, 0.1);}.drop-area p {margin: 5px 0;color: #666;}.drop-area .el-icon--upload {font-size: 50px;color: #999;}
</style>

@change获取上传file文件

http://www.xdnf.cn/news/17626.html

相关文章:

  • WPS文字和Word:不只是表格,段落也可以排序
  • 校园快递小程序(腾讯地图API、二维码识别、Echarts图形化分析)
  • 【Dify学习笔记】:Dify搭建图片文件数据分析助手
  • Kimi K2 架构深度解析:万亿MoE模型的效率革命与智能体突破
  • Linux文件系统:从虚拟接口到物理实现的架构解析
  • 【C++】5. 内存管理
  • Android Studio注释如何不从行首开始
  • gpt-5与gpt-5-fast
  • CPPIO流
  • Postman接口测试:postman设置接口关联,实现参数化
  • 当多模态大语言模型遇上视觉难题!AI视觉探索之旅
  • 视频输入输出模块介绍和示例
  • 编译 BusyBox for ARM 平台
  • 力扣面试150题--爬楼梯 打家劫舍 零钱兑换 最长递增子序列
  • Elasticsearch JS 自定义 ConnectionPool / Connection / Serializer、敏感信息脱敏与 v8 平滑迁移
  • 01-Ansible 自动化介绍与使用
  • 83. 删除排序链表中的重复元素
  • Neo4j Cypher
  • Fiddler国内中文网使用经验分享,从抓包入门到API调试进阶
  • 【读代码】深度解析 Researcher:开源自动化科研助手
  • K8S 节点初始化一键脚本(禁用 SELinux + 关闭 swap + 开启 ipvs 亲测实用)
  • Golang 语言中 Context 的使用方式
  • 计算机视觉(6)-自动驾驶感知方案对比
  • AV、IPS、WAF对比
  • CMake笔记:PUBLIC/PRIVATE/INTERFACE的使用
  • 力扣经典算法篇-50-单词规律(双哈希结构+正反向求解)
  • 微软发布GPT-5赋能的Copilot:重构办公场景的智能革命
  • 【昇腾】关于Atlas 200I A2加速模块macro0配置3路PCIE+1路SATA在hboot2中的一个bug_20250812
  • TensorBoard的使用 小土堆pytorch记录
  • 猫头虎AI分享|腾讯新开源了一个轻量级、即插即用的身份保留视频生成框架:Stand-In,也支持换头像视频