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

Vue3 + Nodejs 实战 ,文件上传项目--实现拖拽上传

目录

 1.拖拽上传的剖析

input的file默认拖动

 让其他的盒子成为拖拽对象

2.处理文件的上传

处理数据

上传文件的函数

兼顾点击事件

渲染已处理过的文件

测试效果

3.总结


 博客主页:専心_前端,javascript,mysql-CSDN博客

 系列专栏:vue3+nodejs 实战--文件上传

 前端代码仓库:jiangjunjie666/my-upload: vue3+nodejs 上传文件的项目,用于学习 (github.com)

 后端代码仓库:jiangjunjie666/my-upload-server: nodejs上传文件的后端 (github.com)

 欢迎关注

在上一篇中,我们实现了文件的批量上传以及显示实时的上传进度,Vue3 + Nodejs 实战 ,文件上传项目--实现文件批量上传(显示实时上传进度)_専心的博客-CSDN博客

该篇主要的是探讨拖拽上传的思路以及实现。 

 1.拖拽上传的剖析

input的file默认拖动

其实在我的目前的认知中(当然我不是很成熟,还在努力学习,如有不对请大佬们多包含),上传文件其实主要就是二点,第一个是页面的交互(拖拽的样式,显示的上传进度条等等),第二个就是网络通信将文件通过post请求发送给后端,所以上传文件的接口我们上期中已经写好了,这次主要是完成前端页面的交互逻辑。

拖拽上传其实在原生的input选择框中本来就是支持的。

 

所以我们可以将input铺满整个上传框中,并且将其opacity设置为0,就能达到隐藏的效果,并且既能支持拖拽还能支持点击。

但是一般情况下实际开发中不会这样做,一般都是根据设计稿来具体实现不同的样式,input框都是隐藏状态,隐藏状态就无法做到拖拽文件到其范围里面了。 

 让盒子成为拖拽对象

上面的input之所以支持拖拽效果,因为在原生的html5中他就是被作为一个拖拽对象存在的,但是兼容性可能不是特别好,这时候我们就可以将其他的盒子也变成一个拖拽对象。

 下面是我们存放整个拖拽上传区域的盒子,我们将其设置为拖拽对象。

<div class="container" @dragenter.prevent="handleDragEnter" @dragover.prevent="handleDragOver" @drop.prevent="handleDrop"></div>

我们在他身上绑定了一些事件

  • dragover 事件:当拖拽对象在一个元素上悬停时(即,拖拽对象在元素上移动时),dragover 事件会持续触发。

  • dragenter 事件:当拖拽对象首次进入一个元素时,dragenter 事件会触发。

  • dragleave 事件:当拖拽对象离开一个元素时,dragleave 事件会触发。

  • drop 事件:当拖拽对象在元素上松开鼠标按钮时,drop 事件会触发。

我们这里只需要将enter和over阻止掉就行

// 处理拖拽进入
const handleDragEnter = (e) => {e.preventDefault()console.log('Drag entered')
}
// 处理拖拽过程中
const handleDragOver = (e) => {e.preventDefault() // 阻止默认行为// 处理拖拽过程中的操作console.log('Drag over')
}
// 处理拖拽事件
const handleDrop = (e) => {e.preventDefault()const files = e.dataTransfer.filesconsole.log('上传的文件:', files)
}

现在就可以实现文件的拖拽上传了,只要拖拽到指定的区域就可以,拿到数据使用的是e.dataTransfer.flies

2.处理文件的上传

处理数据

我们可以定义一个数组放至待上传的文件,一个放置已经进行处理过的文件

//存放已经上传的文件的数组
let fileListOver = ref([])
//存放要上传的文件的数组
let fileList = ref([])

在拖拽事件后数据push进数组中

// 处理拖拽事件
const handleDrop = (e) => {e.preventDefault()const files = e.dataTransfer.filesconsole.log('上传的文件:', files)//将要上传的文件放入数组中fileList.value.push(...files)uploadFile()
}

上传文件的函数

这个上传文件的接口使用的是上一个视频写的接口,没看过的可以翻翻前面的Vue3 + Nodejs 实战 ,文件上传项目--实现文件批量上传(显示实时上传进度)_専心的博客-CSDN博客

接下来就可以进行文件的上传,处理上传的数据,因为我们是可以选择多文件的,所以要递归判断上传文件。在这之前别忘了导入axios的构造函数

 

//上传文件的函数
const uploadFile = async () => {//先要计算出要上传的文件的索引const index = fileListOver.value.lengthif (fileList.value.length == fileListOver.value.length) {//所有的数据都已经上传完毕,退出递归return}//存放文件数据let formData = new FormData()formData.append('file', fileList.value[index])console.log(formData)let res = await http.post('/api/fileUpload', formData)if (res.code !== 200) {fileListOver.value.push({name: fileList.value[index].name,size: fileList.value[index].size > 1024 * 1024 ? (fileList.value[index].size / 1024 / 1024).toFixed(2) + 'mb' : (fileList.value[index].size / 1024).toFixed(2) + 'kb',status: 'error'})ElMessage({type: 'error',message: res.msg})} else {//将上传好的数据插入至fileListOver中fileListOver.value.push({name: fileList.value[index].name,size: fileList.value[index].size > 1024 * 1024 ? (fileList.value[index].size / 1024 / 1024).toFixed(2) + 'mb' : (fileList.value[index].size / 1024).toFixed(2) + 'kb',status: 'scuuess'})ElMessage({type: 'success',message: '上传成功'})}//开个定时器let timer = setTimeout(() => {uploadFile() //递归clearTimeout(timer)}, 1000)
}

兼顾点击事件

因为我们拖拽文件肯定也是支持选择文件的,所以这里做一下兼容,其实很简单,看过前几期的写这个就是信手拈来。

let fileInputRef = ref(null)// input的监听事件
const handlerChange = (e) => {//将点击上传的文件添加到fileList中fileList.value.push(...e.target.files)// 调用函数uploadFile()
}// 点击上传按钮
const handlerUpload = () => {fileInputRef.value.click()
}

渲染已处理过的文件

 <!-- 这里显示已经拖拽上传了的文件 --><el-table :data="fileListOver" style="width: 80%"><el-table-column prop="name" label="文件名" width="450" /><el-table-column prop="size" label="文件大小" width="200" /><!-- 控制显示 --><el-table-column label="文件状态" width="300"><template #default="scope1"><span v-if="scope1.row.status == 'scuuess'" style="color: #67c23a">上传成功</span><span v-if="scope1.row.status == 'error'" style="color: red">上传失败</span></template></el-table-column></el-table>

测试效果

选中

上传中

 

上传完成 

 

全部代码

<template><div class="container" :class="{ draging: dragStyle == true }" @dragenter.prevent="handleDragEnter" @dragover.prevent="handleDragOver" @drop.prevent="handleDrop"><el-icon size="200" class="icon" @click="handlerUpload"><UploadFilled /></el-icon><input type="file" multiple @change="handlerChange" ref="fileInputRef" class="ipt" style="display: none" /></div><!-- 这里显示已经拖拽上传了的文件 --><el-table :data="fileListOver" style="width: 80%"><el-table-column prop="name" label="文件名" width="450" /><el-table-column prop="size" label="文件大小" width="200" /><!-- 控制显示 --><el-table-column label="文件状态" width="300"><template #default="scope1"><span v-if="scope1.row.status == 'scuuess'" style="color: #67c23a">上传成功</span><span v-if="scope1.row.status == 'error'" style="color: red">上传失败</span></template></el-table-column></el-table>
</template><script setup>
import { ref } from 'vue'
import { http } from '@/api/http.js'
import { ElMessage } from 'element-plus'
let fileInputRef = ref(null)
//存放已经上传的文件的数组
let fileListOver = ref([])
//存放要上传的文件的数组
let fileList = ref([])
//拖拽样式
let dragStyle = ref(false)
// input的监听事件
const handlerChange = (e) => {//将点击上传的文件添加到fileList中fileList.value.push(...e.target.files)// 调用函数uploadFile()
}// 点击上传按钮
const handlerUpload = () => {fileInputRef.value.click()
}// 处理拖拽进入
const handleDragEnter = (e) => {e.preventDefault()//添加拖拽样式dragStyle.value = true
}
// 处理拖拽过程中
const handleDragOver = (e) => {e.preventDefault() // 阻止默认行为
}
// 处理拖拽事件
const handleDrop = (e) => {e.preventDefault()const files = e.dataTransfer.filesconsole.log('上传的文件:', files)//将要上传的文件放入数组中fileList.value.push(...files)dragStyle.value = falseuploadFile()
}
//上传文件的函数
const uploadFile = async () => {//先要计算出要上传的文件的索引const index = fileListOver.value.lengthif (fileList.value.length == fileListOver.value.length) {//所有的数据都已经上传完毕,退出递归return}//存放文件数据let formData = new FormData()formData.append('file', fileList.value[index])console.log(formData)let res = await http.post('/api/fileUpload', formData)if (res.code !== 200) {fileListOver.value.push({name: fileList.value[index].name,size: fileList.value[index].size > 1024 * 1024 ? (fileList.value[index].size / 1024 / 1024).toFixed(2) + 'mb' : (fileList.value[index].size / 1024).toFixed(2) + 'kb',status: 'error'})ElMessage({type: 'error',message: res.msg})} else {//将上传好的数据插入至fileListOver中fileListOver.value.push({name: fileList.value[index].name,size: fileList.value[index].size > 1024 * 1024 ? (fileList.value[index].size / 1024 / 1024).toFixed(2) + 'mb' : (fileList.value[index].size / 1024).toFixed(2) + 'kb',status: 'scuuess'})ElMessage({type: 'success',message: '上传成功'})}//开个定时器let timer = setTimeout(() => {uploadFile() //递归clearTimeout(timer)}, 1000)
}
</script><style lang="scss" scoped>
.container {width: 800px;height: 300px;margin: 20px 100px;border: 2px dashed #ccc;display: flex;justify-content: center;align-items: center;.ipt {width: 100%;height: 100%;opacity: 0;display: none;}.icon {color: #ccc;}.icon:hover {cursor: pointer;}//拖拽样式.draging {background-color: #ecf5ff;border: 2px dashed #eaebec;.icon {color: pink;}}
}
</style>

3.总结

 拖拽上传的本质就是用户与页面的交互,其实涉及到的难点不多,只要懂得了设置div或者某个容器为拖拽对象,这种拖拽上传的问题就迎刃而解了,如有不理解或更好的方案可以私信或评论交流。

下一篇准备实现大文件的分片上传,欢迎关注。

相关文章:

Vue3 + Nodejs 实战 ,文件上传项目--实现拖拽上传

目录 1.拖拽上传的剖析 input的file默认拖动 让其他的盒子成为拖拽对象 2.处理文件的上传 处理数据 上传文件的函数 兼顾点击事件 渲染已处理过的文件 测试效果 3.总结 博客主页&#xff1a;専心_前端,javascript,mysql-CSDN博客 系列专栏&#xff1a;vue3nodejs 实战-…...

Windows:VS Code IDE安装ESP-IDF【保姆级】

物联网开发学习笔记——目录索引 参考&#xff1a; VS Code官网&#xff1a;Visual Studio Code - Code Editing. Redefined 乐鑫官网&#xff1a;ESP-IDF 编程指南 - ESP32 VSCode ESP-ID Extension Install 一、前提条件 Visual Studio Code IDE安装ESP-IDF扩展&#xf…...

Hadoop3教程(十一):MapReduce的详细工作流程

文章目录 &#xff08;94&#xff09;MR工作流程Map阶段Reduce阶段 参考文献 &#xff08;94&#xff09;MR工作流程 本小节将展示一下整个MapReduce的全工作流程。 Map阶段 首先是Map阶段&#xff1a; 首先&#xff0c;我们有一个待处理文本文件的集合&#xff1b; 客户端…...

测试中Android与IOS分别关注的点

目录 1、自身不同点 2、测试注重点 3、其他测试点 主要从本身系统的不同点、系统造成的不同点、和注意的测试点做总结 1、自身不同点 研发商&#xff1a;Adroid是google公司做的手机系统&#xff0c;IOS是苹果公司做的手机系统   开源程度&#xff1a;Android是开源的&a…...

NLG(自然语言生成)评估指标介绍

诸神缄默不语-个人CSDN博文目录 本文介绍自然语言生成任务中的各种评估指标。 因为我是之前做文本摘要才接触到这一部分内容的&#xff0c;所以本文也是文本摘要中心。 持续更新。 文章目录 1. 常用术语2. ROUGE (Recall Oriented Understudy for Gisting Evaluation)1. 计算…...

苍穹外卖(七) Spring Task 完成订单状态定时处理

Spring Task 完成订单状态定时处理, 如处理支付超时订单 Spring Task介绍 Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代码逻辑。 应用场景: 信用卡每月还款提醒 火车票售票系统处理未支付订单 入职纪念日为用户发送通知 点外…...

【探索Linux】—— 强大的命令行工具 P.11(基础IO,文件操作)

阅读导航 前言一、C语言的文件操作二、C的文件操作三、Linux系统文件操作&#xff08;I/O接口&#xff09;1. open()⭕传入多个打开方式&#xff08;按位或操作将不同的标志位组合在一起&#xff09; 2. write()3. read()4. close()5. lseek() 温馨提示 前言 前面我们讲了C语言…...

前端练习项目(附带页面psd图片及react源代码)

一、前言 相信很多学完前端的小伙伴都想找个前端项目练练手&#xff0c;检测自己的学习成果。但是现在很多项目市面上都烂大街了。今天给大家推荐一个全新的项目——电子校园 项目位置&#xff1a;https://github.com/v5201314/eSchool 二、项目介绍(部分页面展示)&#xff…...

【从零开始学习Redis | 第三篇】在Java中操作Redis

前言&#xff1a; 本文算是一期番外&#xff0c;介绍一下如何在Java中使用Reids &#xff0c;而其实基于Java我们有很多的开源框架可以用来操作redis&#xff0c;而我们今天选择介绍的是其中比较常用的一款&#xff1a;Spring Data Redis 目录 前言&#xff1a; Spring Data…...

vim、gcc/g++、make/Makefile、yum、gdb

vim、gcc/g、make/Makefile、yum、gdb 一、Linux编辑器vim1、简介2、三种模式的概念&#xff08;1&#xff09;正常/普通/命令模式(Normal mode)&#xff08;2&#xff09;插入模式(Insert mode)&#xff08;3&#xff09;末行/底行模式(last line mode) 3、三种模式的切换4、正…...

2022最新版-李宏毅机器学习深度学习课程-P13 局部最小值与鞍点

一、优化失败的原因 局部最小值&#xff1f;鞍点&#xff1f; 二、数学推导分析 用泰勒公式展开 一项与梯度&#xff08;L的一阶导&#xff09;有关&#xff0c;一项与海赛矩阵&#xff08;L的二阶导&#xff09;有关 海瑟矩阵 VTHV通过海瑟矩阵的性质可以转为判断H是否是正…...

ARM架构的基本知识

ARM两种授权 体系结构授权, 一种硬件规范, 用来约定指令集, 芯片内部体系结构(内存管理, 高速缓存管理), 只约定每一条指令的格式, 行为规范, 参数, 客户根据这个规范自行设计与之兼容的处理器处理IP授权, ARM公司根据某个版本的体系结构设计处理器, 再把处理器设计方案授权给…...

网络安全(黑客技术)——如何高效自学

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学&#xff1f;如何学&#xff1f; 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c…...

云原生场景下高可用架构的最佳实践

作者&#xff1a;刘佳旭&#xff08;花名&#xff1a;佳旭&#xff09;&#xff0c;阿里云容器服务技术专家 引言 随着云原生技术的快速发展以及在企业 IT 领域的深入应用&#xff0c;云原生场景下的高可用架构&#xff0c;对于企业服务的可用性、稳定性、安全性越发重要。通…...

图论-最短路径算法-弗洛伊德算法与迪杰斯特拉算法

弗洛伊德算法&#xff1a; 弗洛伊德算法本质是动态规划&#xff0c;通过添加点进如可选择的点组成的集合的同时更新所有点之间的距离&#xff0c;从而得到每两个点之间的最短距离。 初始化&#xff1a; 创建一个二维数组 dist&#xff0c;其中 dist[i][j] 表示从节点 i 到节点…...

[23] IPDreamer: Appearance-Controllable 3D Object Generation with Image Prompts

pdf Text-to-3D任务中&#xff0c;对3D模型外观的控制不强&#xff0c;本文提出IPDreamer来解决该问题。在NeRF Training阶段&#xff0c;IPDreamer根据文本用ControlNet生成参考图&#xff0c;并将参考图作为Zero 1-to-3的控制条件&#xff0c;用基于Zero 1-to-3的SDS损失生成…...

深入理解React中的useEffect钩子函数

引言&#xff1a; React是一种流行的JavaScript库&#xff0c;它通过组件化和声明式编程的方式简化了前端开发。在React中&#xff0c;一个核心概念是组件的生命周期&#xff0c;其中包含了许多钩子函数&#xff0c;用于管理组件的不同阶段。其中之一就是useEffect钩子函数&…...

数字化时代的财务管理:挑战与机遇

导语&#xff1a;随着数字化技术的不断发展&#xff0c;财务管理正面临着前所未有的挑战和机遇。数字化不仅改变了财务数据的收集、处理和分析方式&#xff0c;还为财务决策提供了更多的依据和方向。本文将探讨数字化时代财务管理的新特点&#xff0c;以及如何利用数字化技术提…...

网络通信协议-HTTP、WebSocket、MQTT的比较与应用

在今天的数字化世界中&#xff0c;各种通信协议起着关键的作用&#xff0c;以确保信息的传递和交换。HTTP、WebSocket 和 MQTT 是三种常用的网络通信协议&#xff0c;它们各自适用于不同的应用场景。本文将比较这三种协议&#xff0c;并探讨它们的主要应用领域。 HTTP&#xff…...

【深度学习】深度学习实验四——循环神经网络(RNN)、dataloader、长短期记忆网络(LSTM)、门控循环单元(GRU)、超参数对比

一、实验内容 实验内容包含要进行什么实验,实验的目的是什么,实验用到的算法及其原理的简单介绍。 1.1 循环神经网络 (1)理解序列数据处理方法,补全面向对象编程中的缺失代码,并使用torch自带数据工具将数据封装为dataloader。 (2)分别采用手动方式以及调用接口方式…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

BLEU评分:机器翻译质量评估的黄金标准

BLEU评分&#xff1a;机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域&#xff0c;衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标&#xff0c;自2002年由IBM的Kishore Papineni等人提出以来&#xff0c;…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...