大文件上传demo,前端基于Uppy,后端基于koa
前言
文件上传基本上所有的管理系统之类的项目都有这么一个功能。因为使用了Element
,可以方便的使用
其提供的Upload
组件,对于普通上传来说基本上就够用了。但是有时候会涉及到大文件上传的需求,这时就会面临一些问题:比如文件上传超时。
自己做的话很麻烦,需要考虑到的东西非常多。这时可以考虑使用第三方封装的库。这里推荐Uppy
,主要是这个库一直在维护,有些库都是几年前的了,比如WebUploader
。
只是简单的研究,遇到问题,看官方文档
官方文档: https://uppy.io/docs/quick-start/
官方git: https://github.com/transloadit/uppy
准备工作
前端基于vue3,后端基于koa
。(主业前端,后端是业余爱好只是简单了解)
前端
项目创建具体见:使用Vite搭建Vue3 + Ts项目,这里就不介绍了。
搭建完项目需要安装一下:axios
、element-plus
,运行项目后如下图:
后端
项目创建具体见:Koa学习1:初始化项目
运行项目后如下图:
整合
现在处理一下,让vue前端能够请求到数据
后端
需要安装koa2-cors
来解决跨域问题
npm install koa2-cors
修改后的main.js
// 导入Koa
const Koa = require("koa");
// 用于解决跨域
const cors = require("koa2-cors");
// 实例化
const app = new Koa();app.use(cors());// 中间件
app.use(async (ctx, next) => {const start = Date.now();await next();ctx.body = "hellow koa";
});// 监听端口
app.listen(5000, () => {console.log(`app listening at http://localhost:5000`);
});
前端
修改vite.config.ts
配置文件
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';// https://vitejs.dev/config/
export default defineConfig({plugins: [vue()],server: {proxy: {'/api': {target: 'http://localhost:5000/',changeOrigin: true,rewrite: path => path.replace(/^\/api/, '')}}}
});
修改App.vue
<template><div class="upload-container"><el-button type="primary" ="getData">上传</el-button><p>数据是:{{ message }}</p></div>
</template><script setup lang="ts">
import { ref } from 'vue';
import axios from 'axios';const message = ref('');// 请求数据
const getData = () => {axios.get('http://localhost:5000/').then(res => {message.value = res.dataconsole.log("数据是:", res.data)})
}</script><style scoped>
.upload-container {display: flex;justify-content: center;align-items: center;height: 700px;
}
</style>
效果图
简单demo,上传图片
前端
安装uppy
npm install /core /drag-drop /status-bar /xhr-upload
core
核心包drag-drop
用于实现拖拽上传status-bar
显示上传进度条xhr-upload
实现文件上传
<template><div class="upload-container"><div id="drag-drop-area"><!-- 默认样式,也可以在里面进行自定义 --></div><div id="status-bar"></div></div>
</template><script setup lang="ts">
import { ref, onMounted } from "vue"
import { ElMessage } from 'element-plus'import Uppy from '@uppy/core';
import DragDrop from '@uppy/drag-drop';
import StatusBar from '@uppy/status-bar';
import XHRUpload from '@uppy/xhr-upload';//引入样式
import '@uppy/core/dist/style.min.css';
import '@uppy/drag-drop/dist/style.min.css';// 1mb大小
const ONE_MB = 1024 * 1024;const uppy = ref()onMounted(() => {uppy.value = new Uppy({debug: true, // 允许拖拽autoProceed: false, // 是否自动上传restrictions: {maxFileSize: 10 * ONE_MB, // 设置最大文件大小maxNumberOfFiles: 5, // 设置最大上传文件数量allowedFileTypes: ['.jpg', '.jpeg', '.png'] // 设置允许的文件类型}}).use(DragDrop, { target: '#drag-drop-area', note: '拖放或点击' }) // 启用拖动.use(StatusBar, { target: '#status-bar' }) //启用进度条.use(XHRUpload, {endpoint: 'http://localhost:5000/upload', // 设置上传文件的API接口formData: true // 启用FormData发送数据});// 监听文件上传uppy.value.on('upload-success', (file: any, response: any) => {// console.log("上传的文件:", file)console.log("返回的信息:", response)if (response.body.code == 0) {ElMessage.success(`文件${file.name}上传成功`)} else {ElMessage.error(`文件${file.name}上传失败,${response.body.message}`)}})
})</script><style scoped>
.upload-container {display: flex;justify-content: center;align-items: center;height: 700px;
}
</style>
后端
安装koa-body
中间件,它可以方便地处理请求体中的文件数据。
npm install koa-body
安装koa-router
中间件,用于post
请求
npm install koa-router
修改main.js
// 导入Koa
const Koa = require("koa");
// 用于解决跨域
const cors = require("koa2-cors");
// 用于文件上传
const { koaBody } = require("koa-body");
// 用于处理路径
const path = require("path");
// 引入路由
const Router = require("koa-router");// 注意如果有改动,则要重启一下。如果觉得麻烦可以设置热重启,具体见:https://blog.csdn.net/weixin_41897680/article/details/130907232// 实例化
const app = new Koa();
const router = new Router();app.use(cors());// 配置文件上传
app.use(koaBody({multipart: true, // 允许多文件formidable: {uploadDir: path.join(__dirname, "uploads"), // 设置文件上传目录,必须有这个文件夹不然会报错keepExtensions: true, // 保持文件扩展名},})
);router.get("/", async (ctx) => {ctx.body = "hello Koa";
});// 文件上传
router.post("/upload", async (ctx) => {// 获取上传的文件try {const file = await ctx.request.files.file;console.log("文件信息:", file);ctx.body = {message: "文件上传成功",data: {size: file.size, //文件大小fileName: file.originalFilename, // 文件的原始名称filePath: file.filepath, // 在服务器上的保存路径updateTime: file.lastModifiedDate, // 上次修改的时间},};} catch (err) {ctx.body = {message: err,data: {},};}
});//挂载路由
app.use(router.routes()).use(router.allowedMethods());// 监听端口
app.listen(5000, () => {console.log(`app listening at http://localhost:5000`);
});
大文件上传、断点续传
实现分片上传并且支持断点续传需要基于Tus
Tus 是一种开放协议,用于基于 HTTP 构建的可恢复上传。这意味着 意外关闭选项卡或失去连接,让您继续,对于 实例,您的 10GB 上传,而不是重新开始。
Tus 支持任何语言、任何平台和任何网络。它需要一个客户端 和服务器集成工作。您可以签出客户端和服务器实现,以查找首选语言的服务器。
前端
前端变化不大,Uppy
为我们提供了对应的插件,修改后的代码如下:
<!-- 大文件上传 -->
<template><div class="upload-container"><div id="drag-drop-area"><!-- 默认样式,也可以在里面进行自定义 --></div><div id="status-bar"></div><br /><el-button type="primary" ="pauseOrResume">{{ isUploadding ? '暂停' : '开始' }}</el-button></div>
</template><script setup lang="ts">
import { ref, onMounted } from "vue"
import { ElMessage } from 'element-plus'import Uppy from '@uppy/core';
import DragDrop from '@uppy/drag-drop';
import StatusBar from '@uppy/status-bar';
import Tus from '@uppy/tus';//引入样式
import '@uppy/core/dist/style.min.css';
import '@uppy/drag-drop/dist/style.min.css';// 1mb大小
const ONE_MB = 1024 * 1024;
// 是否正在上传,默认在上传
const isUploadding = ref(true)let uppy: Uppy;onMounted(() => {uppy = new Uppy({debug: true, // 允许拖拽autoProceed: false, // 是否自动上传restrictions: {maxFileSize: 300 * ONE_MB, // 设置最大文件大小maxNumberOfFiles: 5, // 设置最大上传文件数量allowedFileTypes: ['.jpg', '.jpeg', '.png', '.zip'] // 设置允许的文件类型},}).use(DragDrop, { target: '#drag-drop-area', note: '拖放或点击' }) // 启用拖动.use(StatusBar, { target: '#status-bar' }) //启用进度条.use(Tus, {endpoint: 'http://127.0.0.1:5000/files', // 设置上传文件的API接口limit: 5, // 限制同时进行的上传数量,默认值20,不要没有限制或者过大chunkSize: 5 * ONE_MB // 设置分片的大小});// 监听文件上传uppy.on('complete', (result: any) => {// result是一个对象,属性是:// 会返回failed(Array),因为可以多文件上传会返回一个数组// successful(Array),因为可以多文件上传会返回一个数组,包含文件上传成功的信息console.log("上传完成:",result)if (Array.isArray(result.failed) && result.failed.length>0) {ElMessage.error(`文件上传失败,${result.failed}`)} else {ElMessage.success(`文件上传成功`)}})
})// 暂停与恢复
const pauseOrResume = () => {if (isUploadding.value) {// 正在上传uppy.pauseAll()} else {// 暂停中uppy.resumeAll()}isUploadding.value = !isUploadding.value
}</script><style scoped>
.upload-container {width: 300px;margin: 100px auto;height: 700px;
}
</style>
后端
后端变化挺大的,你需要将你的服务器变得支持Tus
,刚好官方提供了对应的插件(Java后台、php后台可以自行百度如何集成)
插件官方文档
https://github.com/tus/tus-node-server
官方集成案例,这个很重要,会介绍插件的属性、事件等
https://github.com/tus/tus-node-server/tree/main/packages/server
安装
npm i /file-store /server tus-node-server
代码
const Koa = require("koa");
const { Server } = require("@tus/server");
const { FileStore } = require("@tus/file-store");
// 用于解决跨域
const cors = require("koa2-cors");const host = "127.0.0.1";
const port = 5000;
// 创建一个tusServer服务
const tusServer = new Server({path: "/files", // 路由datastore: new FileStore({ directory: "./files" }), // 文件存储的位置
});const app = new Koa();app.use(cors());// 将 tus-server 添加为 Koa 的中间件
app.use(async (ctx, next) => {// 注:tus-server 的处理程序要求精确匹配路由路径,这里无法使用koa-router。只能当作一个单独的中间件使用await tusServer.handle.bind(tusServer)(ctx.req, ctx.res);
});// 注:tus-server 的处理程序要求精确匹配路由路径,这里无法使用koa-router。只能当作一个单独的中间件使用app.listen(port, host, () => {console.log(`Server is running on http://${host}:${port}`);
});
执行效果
上传完成后会生成两个文件,如下:
第一个就是上传的文件,会变成一个二进制文件
第二个是这个文件的一下信息
前端Uppy
库也会返回文件信息,如下图:
代码
代码放到码云上了,感兴趣的可以自己看一下
前端
地址
https://gitee.com/idonotyou/vue-upload
运行
npm i
npm run dev
后端
地址
https://gitee.com/idonotyou/koa-upload
运行
npm i
npm run dev
相关文章:

大文件上传demo,前端基于Uppy,后端基于koa
前言 文件上传基本上所有的管理系统之类的项目都有这么一个功能。因为使用了Element,可以方便的使用 其提供的Upload组件,对于普通上传来说基本上就够用了。但是有时候会涉及到大文件上传的需求,这时就会面临一些问题:比如文件上…...
typeScript--[函数定义]
一.TypesScript 函数的定义 函数的定义包括两种类型:函数声明和函数表达式。 1.函数声明 function hello(): string {return "hello" } 2.函数表达式 var hello1 function (): string {return "hello" } 二.函数之可选参数 参数后面的限…...

Spring初始化项目
1、官网用法 访问地址:https://start.spring.io idea配置:https://start.spring.io 2、阿里巴巴加速 访问地址:https://start.aliyun.com/bootstrap.html idea配置:https://start.aliyun.com 3、区别 官网阿里巴巴版本最新稍…...

Opencv 图像金字塔----高斯和拉普拉斯
原文:图像金字塔----高斯和拉普拉斯 图像金字塔是图像中多尺度表达的一种,最初用于机器视觉和图像压缩,最主要用于图像的分割、融合。 高斯金字塔 ( Gaussian pyramid): 高斯金字塔是由底部的最大分辨率图像逐次向下采样得到的一系列图像…...

gitLab(git)误提交命令
1.先使用下面命令查看一下分支上已提交的信息 git log 2.回退到之前的版本 git reset —hard 你要删除的提交哈希码(一般是离这个命令最近的一串数字) 3.覆盖掉远端的版本信息,使远端的仓库也回退到相应的版本 注意:切换到你提…...
Rust个人学习笔记2
一定要牢记Rust是基于表达式的语言,除了声明语句和表达式语句外,其他的都是表达式。所以if也是表达式,它可以被用作右值。 条件控制 if-else。cpp和python得结合。 fn main() {let number 34;if number < 0 {println!("number &l…...

深入浅出Android同步屏障机制
原文链接 Android Sync Barrier机制 诡异的假死问题 前段时间,项目上遇到了一个假死问题,随机出现,无固定复现规律,大量频繁随机操作后,便会出现假死,整个应用无法操作,不会响应事件ÿ…...

工程管理系统简介 工程管理系统源码 java工程管理系统 工程管理系统功能设计
鸿鹄工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离构建工程项目管理系统 1. 项目背景 一、随着公司的快速发展,企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性,公司对内部工程管…...
Python 专栏目录索引
文章目录 Python 环境搭建Python 语法 变量、print、注释和运算符Python 的基本结构Python 中的文件和文件夹操作Python 中常用库Python 常见问题及解决方案Python 应用实例 Python 环境搭建 vscode搭建Python环境 Python 语法 变量、print、注释和运算符 python语法 变量、…...
SSM学习
技术架构 crm的技术架构: 视图层(view):展示数据,跟用户交互。 html, css,js,jquery,bootstrap(ext / easyUI),jsp控制层(Controller):控制业客处理流程(接收请求,接收参数,封装参数;根据不同的请求调用业务 (servlet, ) springMVC ( , webwork,strutsl,struts2)业…...
.net项目部署Docker
1、项目生成的bin目录下创建Dockerfile文件 #运行环境描述,此处是用的Net5构建镜像 FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build #复制文件到 docker容器中的app文件夹中 COPY . /app #设置工作目录为 app 文件夹,要和上面一致哦 WORKDIR /app #设…...
Ubuntu无法加载exfat的USB存储设备
当接入设备USB存储设备提示: 不能挂在63GB 卷 Error mounting /dev/sdb1 at /media/ubuntu/83C9-26F4: Command-line mount -t "exfat" -o "uhelperudisks2,nodev,nosuid,uid1000,gid1000,iocharsetutf8,namecase0,errorsremount-ro,umask0077"…...
【计算机网络】网络编程接口 Socket API 解读(2)
Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。 本文讲述的 socket 内容源自 Linux 发行版 centos 9 上的 man 工具,和其他平台(比如 os-x …...
【黄啊码】PHP如何防止重复提交
防抖(Debounce)是一种防止重复提交的策略,它通过延迟一定时间来合并连续的操作,以确保只执行一次。 以下是几种防抖的实现方法以及对应的代码示例: 1. 前端 JavaScript 实现: 在前端使用 JavaScript 实现…...

2594. 修车的最少时间
文章目录 Tag题目来源题目解读解题思路方法一:二分枚举答案 写在最后 Tag 【二分枚举答案】【数组】 题目来源 2594. 修车的最少时间 题目解读 给你一个表示机械工能力的数组 ranks,ranks[i] 表示第 i 位机械工可以在 r a n k s [ i ] ∗ n 2 ranks[…...

vue 使用qrcode生成二维码并可下载保存
安装qrcode npm install qrcode --save代码 <template><div style"display: flex; flex-direction: column; align-items: center; justify-content center;"><div>查看溯源码,<a id"saveLink" style"text-decorati…...
网络融合的发展思路
虽然移动和固定网的融合代表了下一代网络的发展方向,但是目前移动和固定网的 发展还是独立的,有着各自的演进方式,要实现两个网络的完全融合是一个长期 的、逐步发展的过程。 网络融合的体系结构首先应坚持网络分层和功能分离的原则&#…...

报考浙江工业大学MBA项目如何选择合适的辅导班?
浙江工业大学MBA项目每年有数百人报考,在浙江省内除了浙大以外算是人数比较多的一个项目。2023级的招生中第一志愿也通过复试刷掉了百来人,在省内其实作为第一志愿报考的风险在逐渐增大,考生们如果坚持报考,则在针对联考初试的备考…...
算法训练第五十八天
总结:今日事单调栈的开端,还是挺巧妙的。 496. 下一个更大元素 I - 力扣(LeetCode) 代码: class Solution { public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& …...
如何快速生成一个H5滑动的卡片(单页和分页都有)
单页 <ul class"combo"><li v-for"(item, index) in arr" :key"index"><div class"combo-name">{{ item.A }}</div><div class"combo-price">{{ item.B }}</div><div class"co…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...

基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...