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

大文件上传全方案:Vue + Node.js 实战

1 为什么需要大文件上传方案?

在视频平台、云存储、数据备份等场景中,GB 级文件上传是常见需求。直接上传大文件会面临三大核心问题:

  1. 网络不稳定:单次上传失败需重新上传整个文件,耗时耗力;
  2. 超时风险:大文件上传耗时久,易触发服务器/客户端超时;
  3. 资源占用过高:前端一次性读取大文件到内存会导致页面卡顿,后端一次性接收大文件会占用大量内存和带宽。

解决方案的核心是分片上传—— 将大文件切割为小分片,逐个传输后在服务器合并,配合断点续传、秒传等机制,实现高效可靠的传输。

2 前端实现(Vue 3)

2.1 技术栈

  • 框架:Vue 3(Composition API)

  • UI 组件:Ant Design Vue(提供上传区域、进度条等基础组件)

  • 网络请求:Axios(处理分片上传、合并请求)

  • 多线程:Web Worker(避免哈希计算阻塞主线程)

  • 哈希计算:SparkMD5(高效计算大文件哈希,用于秒传和分片标识)

2.2 实现方案

2.2.1 项目结构

upload-demo/
├── public/
│   ├── index.html
│   ├── filenameWorker.js
│   └── spark-md5.min.js  // 本地存储SparkMD5库,避免CDN依赖
├── src/
│   ├── utils/
│   │   └── request.js   
│   ├── components/
│   │   └── FileUploader.vue  // 核心上传组件
│   ├── App.vue
│   └── main.js
├── package.json
└── vite.config.js

2.2.2 public/spark-md5.min.js

 从SparkMD5 官网下载最新版本,保存到public目录,避免依赖 CDN。

2.2.3 package.json

{"name": "upload-demo","version": "0.0.0","scripts": {"dev": "vite","build": "vite build","preview": "vite preview"},"dependencies": {"@ant-design/icons-vue": "^7.0.1","ant-design-vue": "^4.0.6","axios": "^1.6.0","vue": "^3.3.4"},"devDependencies": {"@vitejs/plugin-vue": "^4.4.0","vite": "^4.4.11"}
}

2.2.4 vite.config.js

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";export default defineConfig({plugins: [vue()],server: {port: 3000,proxy: {"/upload": {target: "http://localhost:8080",changeOrigin: true,},"/verify": {target: "http://localhost:8080",changeOrigin: true,},"/merge": {target: "http://localhost:8080",changeOrigin: true,},},},
});

2.2.5  public/index.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><link rel="icon" type="image/svg+xml" href="/favicon.ico" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>大文件上传演示</title></head><body><div id="app"></div><script type="module" src="/src/main.js"></script></body>
</html>

2.2.6 public/filenameWorker.js

// public/filenameWorker.js
self.importScripts("/spark-md5.min.js"); // 引入 SparkMD5 库self.addEventListener("message", async (e) => {const file = e.data;const filename = await getFileName(file);self.postMessage(filename);
});async function getFileName(file) {const fileHash = await calculateHash(file);const ext = file.name.split(".").pop();return `${fileHash}.${ext}`;
}async function calculateHash(file) {const chunkSize = 100 * 1024 * 1024; // 100MB/片(与上传分片大小一致)const chunks = Math.ceil(file.size / chunkSize);const spark = new SparkMD5.ArrayBuffer();const fileReader = new FileReader();let currentChunk = 0;return new Promise((resolve, reject) => {fileReader.onload = function (e) {spark.append(e.target.result);currentChunk++;// 实时发送进度(供前端显示)const progress = Math.floor((currentChunk / chunks) * 100);self.postMessage({ type: "progress", progress });// 分时间片处理,避免长时间占用CPUif (currentChunk < chunks) {setTimeout(loadNextChunk, 0); // 每个分片都使用setTimeout} else {const hash = spark.end();resolve(hash); // 直接返回哈希,不进行缓存}};fileReader.onerror = reject;function loadNextChunk() {try {const start = currentChunk * chunkSize;const end = Math.min(start + chunkSize, file.size);fileReader.readAsArrayBuffer(file.slice(start, end));} catch (err) {self.postMessage({ type: "error", error: err.message });}}loadNextChunk();});
}

2.2.7 src/App.vue

<template><div id="app"><h1 style="text-align: center; margin: 20px 0">大文件上传演示</h1><FileUploader /></div>
</template><script setup>
import FileUploader from "./components/FileUploader.vue";
</script><style>
#app {max-width: 1200px;margin: 0 auto;padding: 20px;font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;
}
</style>

2.2.8 src/main.js

import { createApp } from "vue";
import App from "./App.vue";
import Antd from "ant-design-vue";
import "ant-design-vue/dist/reset.css";const app = createApp(App);
app.use(Antd);
app.mount("#app");

2.2.9 src/components/FileUploader.vue

<template><div class="upload-container"><!-- 上传区域 --><divref="uploadArea"class="upload-area"@dragenter.prevent@dragover.prevent@drop.prevent="handleDrop"@click="handleClick"><!-- 文件预览 --><div v-if="filePreview.url" class="preview-container"><videov-if="filePreview.type.startsWith('video/')":src="filePreview.url"controlsclass="preview-media"></video><imgv-else-if="filePreview.type.startsWith('image/')":src="filePreview.url"class="preview-media"alt="预览"/></div><template v-else><InboxOutlined class="upload-icon" /><p>点击或拖拽文件到此处上传</p><p class="hint">支持图片、视频格式,最大支持2GB</p></template></div><!-- 控制按钮 --><div class="control-buttons"><Button @click="handleUploadAction"><component :is="getButtonIcon" />{{ getButtonText }}</Button><Buttonv-if="uploadStatus !== 'NOT_STARTED'"type="text"danger@click="cancelUpload"style="margin-left: 10px">取消上传</Button></div><!-- 进度显示 --><div v-if="uploadStatus !== 'NOT_STARTED'" class="progress-container"><!-- 哈希计算进度 --><div v-if="hashProgress > 0 && hashProgress < 100" class="hash-progress"><span>计算文件哈希:</span><Progress :percent="hashProgress" size="small" status="active" /></div><!-- 分片进度(只显示前5个和最后1个,避免过多DOM) --><divv-for="(percent, chunkName) in visibleChunkProgress":key="chunkName"class="chunk-progress"><span>分片{{ chunkName.split("-").pop() }}:</span><Progress v-if="percent !== null" :percent="percent" size="small" :key="chunkName"/></div><!-- 总进度和速度信息 --><div class="total-progress" v-if="Object.keys(uploadProgress).length > 0"><span>总进度:</span><Progress :percent="totalProgress" status="active" /><div class="upload-info"><span>速度: {{ uploadSpeed }} MB/s</span><span>剩余时间: {{ remainingTime }}s</span></div></div></div><!-- 计算文件名加载中 --><Spin v-if="calculatingFilename" tip="计算文件哈希中..."></Spin></div
http://www.dtcms.com/a/602710.html

相关文章:

  • SCI精读:基于计算机视觉改进光伏热点和积尘检测:基于现场航拍图像的YOLO模型系统比较
  • 专门做创意桌椅的网站谷歌play商店
  • 怎么查看网站是否做静态化处理0基础如何做网站
  • 基于MATLAB绘制CALIPSO Level 2产品中体积退偏比垂直廓线和频率分布直方图
  • 青岛网站推广哪家效果好搜索引擎营销案例分析
  • 网站网站如何做的充值下载网站开发
  • 做网站公司广州ip地址免费
  • MATLAB中海洋要素计算工具箱解析
  • 网站开发备案需要什么wordpress入门教程(视频)
  • 哪里有网站开发技术怎样优化排名自己网站
  • 重组蛋白基础与技术概述
  • 利用systick定时器获取微秒计数
  • 如何用易语言做网站小说网站的网编具体做哪些工作
  • CAN总线协议:帧格式
  • 企业微信AI怎么用?从智能表格落地看如何提升运营效率
  • 昆明做网站seo南昌公司网站建设
  • 知寰Hybrid RAG:不止于图谱,重新定义GraphRAG的行业智能新范式
  • 上海网站建设企业建站方一凡和磊儿做家教的网站
  • SQLiteStudio基本操作教程
  • Labview进阶04:Labview与OPC UA设备通信(dll版)
  • 江苏网站建设wordpress域名配置
  • 德州市建设街小学网站首页wordpress的文章多重筛选
  • 加密货币均线策略与传统MACD(介绍下回测框架的择时功能)
  • 青海建设厅报名网站软件工程课程设计题目
  • 网站制作 牛商网中文域名到期对网站的影响
  • 《雷电模拟器9》 [9.1.76.0][x64] [绿色纯净版] 下载
  • 网站建设要点自助建站推广
  • 开发网站的基本流程网站制作怎么做框架
  • 【经典书籍】《代码整洁之道》第十三章“并发编程”精华讲解
  • 绵阳成套配电柜厂家