大文件上传之断点续传实现方案与原理详解

news2025/4/17 6:03:18

一、实现原理

文件分块:将大文件切割为固定大小的块(如5MB)
进度记录:持久化存储已上传分块信息
续传能力:上传中断后根据记录继续上传未完成块
块校验机制:通过哈希值验证块完整性
合并策略:所有块上传完成后进行有序合并

二、前端实现(JavaScript)

// 文件分块(示例使用Blob.slice)
// 默认 5M 一个片段
function createChunks(file, chunkSize = 5 * 1024 * 1024) {
  const chunks = [];
  let offset = 0;
  
  while (offset < file.size) {
    const chunk = file.slice(offset, offset + chunkSize);
    chunks.push({
      chunk,
      index: chunks.length,
      hash: file.name + '-' + chunks.length
    });
    offset += chunkSize;
  }
  return chunks;
}

// 上传控制器
class Uploader {
  constructor(file) {
    this.file = file
    this.chunks = createChunks(file)
    this.uploaded = new Set() // 已上传分块索引
  }

  async checkProgress() {
    // 查询服务端已上传分块
    const { data } = await axios.get('/progress', {
      params: { hash: this.fileHash }
    })
    this.uploaded = new Set(data.uploaded)
  }

  async upload() {
    await this.checkProgress()
    
    for (const chunk of this.chunks) {
      if (this.uploaded.has(chunk.index)) continue
      
      const formData = new FormData()
      formData.append('chunk', chunk.chunk)
      formData.append('hash', chunk.hash)
      formData.append('index', chunk.index)
      formData.append('total', this.chunks.length)
      
      await axios.post('/upload', formData, {
        onUploadProgress: progress => {
          console.log(`${chunk.index}上传进度:`, progress)
        }
      })
      this.uploaded.add(chunk.index)
    }
    
    await axios.post('/merge', { 
      filename: this.file.name,
      total: this.chunks.length 
    })
  }
}

三、服务端实现(Node.js + Express

const express = require('express')
const fs = require('fs-extra')
const path = require('path')
const app = express()

// 临时存储目录
const UPLOAD_DIR = path.resolve(__dirname, 'temp')

// 处理分块上传
app.post('/upload', async (req, res) => {
  const { chunk, hash, index } = req.files
  const chunkDir = path.resolve(UPLOAD_DIR, hash.split('-')[0])
  
  await fs.ensureDir(chunkDir)
  await fs.move(chunk.path, path.resolve(chunkDir, hash))
  
  res.json({ code: 0 })
})

// 合并分块
app.post('/merge', async (req, res) => {
  const { filename, total } = req.body
  const fileHash = filename + '-' + Date.now()
  const chunkDir = path.resolve(UPLOAD_DIR, fileHash)
  const destFile = path.resolve(UPLOAD_DIR, filename)
  
  // 按索引顺序合并
  await fs.ensureDir(chunkDir)
  for (let i = 0; i < total; i++) {
    const chunkPath = path.resolve(chunkDir, `${fileHash}-${i}`)
    await fs.appendFile(destFile, await fs.readFile(chunkPath))
    await fs.unlink(chunkPath)
  }
  
  await fs.rmdir(chunkDir)
  res.json({ code: 0 })
})

// 查询上传进度
app.get('/progress', async (req, res) => {
  const { hash } = req.query
  const chunkDir = path.resolve(UPLOAD_DIR, hash.split('-')[0])
  
  if (!await fs.pathExists(chunkDir)) {
    return res.json({ uploaded: [] })
  }
  
  const uploaded = (await fs.readdir(chunkDir))
    .map(name => parseInt(name.split('-').pop()))
    
  res.json({ uploaded })
})

四、关键实现步骤

分块生成:前端使用Blob.slice进行文件切割
唯一标识:使用"文件名+哈希值"生成文件唯一标识

断点记录
服务端保存每个文件的分块目录
使用Set结构记录已上传分块索引

恢复机制
上传前先查询服务端上传进度
跳过已上传成功的分块

合并验证
按索引顺序合并保证文件正确性
合并完成后清理临时分块

五、注意事项

哈希校验:对每个分块计算MD5进行完整性验证
并发控制:前端使用Promise.all实现并行上传
错误重试:为每个分块添加重试机制
秒传功能:通过文件哈希值检测服务端已存在文件
分块大小自适应:根据网络状况动态调整分块尺寸

该方案,支持TB级文件上传,通过分块策略断点记录机制可显著提升大文件传输的可靠性。
实际部署时建议结合对象存储服务实现,可进一步降低服务器存储压力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2330546.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第一次3D打印,一个简单的小方块(Rhino)

一、建模 打开犀牛&#xff0c;我们选择立方体 我们点击上册的中心点 输入0&#xff0c;然后回车0 而后我们输长度&#xff1a;10&#xff0c;回车确认 同样的&#xff0c;宽度10 高度同样是10 回车确认后&#xff0c;我们得到一个正方形 二、导出模型 我们选择文件—>保存…

VMware-workstation-full-12.5.2 install OS X 10.11.1(15B42).cdr

手把手虚拟机安装苹果操作系统 VMware_workstation_full_12.5.2 unlocker208 Apple Max OS X(M&#xff09;-CSDN博客 vcpu-0:VERIFY vmcore/vmm/main/physMem_monitor.c:1180 FILE: FileCreateDirectoryRetry: Non-retriable error encountered (C:\ProgramData\VMware): Cann…

[ctfshow web入门] web16

信息收集 提示&#xff1a;对于测试用的探针&#xff0c;使用完毕后要及时删除&#xff0c;可能会造成信息泄露 试试url/phpinfo.php url/phpsysinfo.php url/tz.php tz.php能用 点击phpinfo&#xff0c;查看phpinfo信息&#xff0c;搜索flag&#xff0c;发现flag被保存为变量…

全面支持MCP协议,开启便捷连接之旅,MaxKB知识库问答系统v1.10.3 LTS版本发布

2025年4月7日&#xff0c;MaxKB开源知识库问答系统正式发布v1.10.3 LTS版本。 在MaxKB v1.10.3 LTS版本中&#xff0c;应用方面&#xff0c;MaxKB新增支持MCP调用节点&#xff0c;AI对话节点新增MCP工具调用功能&#xff0c;支持设置MCP服务配置&#xff1b;函数库方面&#x…

VTK知识学习(51)- 交互与Widget(二)

1、交互器样式 前面所讲的观察者/命令模式是 VTK实现交互的方式之一。在前面示例 所示的窗口中可以使用鼠标与柱体进行交互&#xff0c;比如用鼠标滚轮可以对柱体放大、缩小;按下鼠标左键不放&#xff0c;然后移动鼠标&#xff0c;可以转动柱体;按下鼠标左键&#xff0c;同时按…

底盘---麦克纳姆轮(Mecanum Wheel)

一、基本定义与起源 定义&#xff1a;麦克纳姆轮是一种实现全向移动的特殊轮式结构&#xff0c;通过在主轮周边安装多个倾斜的辊子&#xff08;小轮&#xff09;&#xff0c;使设备能够在平面上向任意方向移动&#xff08;包括横向、斜向、旋转等&#xff09;&#xff0c;无需…

深入源码级别看spring bean创建过程

我们通常聊到spring bean的生命周期&#xff0c;大多是从网上找帖子背些基本概念&#xff0c;这样我们学到的东西是不够直观清晰的&#xff0c;这篇文章我就试着从源码级别来讲清楚bean的创建过程。 一、准备demo代码 我们既然要深入源码来看bean的创建过程&#xff0c;那么就…

I/O进程1

day1 一、标准IO 1.概念 在C库中定义的一组用于输入输出的函数 2.特点 (1).通过缓冲机制减少系统调用&#xff0c;提高效率 (2.)围绕流进行操作&#xff0c;流用FILE *来描述(3).标准IO默认打开了三个流&#xff0c;stdin&#xff08;标准输入&#xff09;、stdout&#xff08;…

解决Python与Anaconda中pip的冲突,安装包失败问题(此应用无法在你电脑上运行,无法访问)

1、Anaconda安装在D盘 2、Python安装在C盘&#xff08;当时刚换电脑&#xff0c;新电脑还未分盘&#xff0c;着急用python直接安装&#xff09; 问题&#xff1a; &#xff08;1&#xff09;winr&#xff0c;cmd无法访问c盘下的pip&#xff0c;安装包失败。采用管理者身份&…

Java全栈面试宝典:JMM内存模型与Spring自动装配深度解析

目录 一、Java内存模型&#xff08;JMM&#xff09;核心原理 &#x1f525; 问题8&#xff1a;happens-before原则全景解析 JMM内存架构图 happens-before八大规则 线程安全验证案例 &#x1f525; 问题9&#xff1a;JMM解决可见性的三大武器 可见性保障机制 volatile双…

AI前端组件库Ant DesIgn X

Ant Design X AI&#xff1a;体验新秩序 Ant Design 团队精心打造 RICH 设计范式&#xff0c;为 AI 界面提供卓越解决方案&#xff0c;引领智能交互新体验。 设计语言与理论 官网&#xff1a; Ant Design X - 轻松打造 AI 驱动的界面。 AI 设计范式 —— RICH 是我们在蚂蚁…

追踪大型语言模型的思维过程:提示词工程重要

追踪大型语言模型的思维过程:提示词工程重要 目录 追踪大型语言模型的思维过程:提示词工程重要**1. 分步思考能力:像人类一样打草稿****2. 跨语言概念词典:突破语言符号的束缚****3. 诗歌押韵规划:神经元提前预留韵脚****4. 编造专业解释:数据模式导致的“客服式回应”**…

BGP路由协议之属性1

公认属性是所有 BGP 路由器都必须能够识别的属性 公认必遵 (Well-known Mandatory) : 必须包括在每个 Update 消息里公认任意 (Well-known Discretionary) : 可能包括在某些 Update 消息里。 可选属性不需要都被 BGP 路由器所识别 可选过渡(OptionalTransitive) : BGP 设备不…

什么是 k8s 的 Taints(污点) 和 Tolerations(容忍度)

什么是 k8s 的 Taints&#xff08;污点&#xff09; 和 Tolerations&#xff08;容忍度&#xff09; 在 Kubernetes&#xff08;K8s&#xff09;中&#xff0c;Taints&#xff08;污点&#xff09;和 Tolerations&#xff08;容忍度&#xff09;用于影响 Pod 调度到节点的行为…

C++类模板的运用

使用vector实现一个简单的本地注册登录系统 注册&#xff1a;将账号密码存入vector里面&#xff0c;注意防重复判断 登录&#xff1a;判断登录的账号密码是否正确 #include <iostream> #include <vector> #include <string> #include <algorithm>us…

coze生成流程图和思维导图工作流

需求&#xff1a;通过coze平台实现生成流程图和思维导图&#xff0c;要求支持文档上传 最终工作流如下&#xff1a; 入参&#xff1a; 整合用户需求文件内容的工作流&#xff1a;https://blog.csdn.net/YXWik/article/details/147040071 选择器分发&#xff0c;不同的类型走…

【数据库】达梦arm64安装

话不多说&#xff0c;快速开始~ 1.下载 进入官网&#xff1a; 产品下载 | 达梦在线服务平台 下载安装包。 选飞腾、鲲鹏都可以&#xff0c;都是arm架构的。我选择的是&#xff1a; 直接下载地址是https://download.dameng.com/eco/adapter/DM8/202502/dm8_20250117_HWarm920…

leetcode274.H指数

直接排序完后进行遍历 class Solution {public int hIndex(int[] citations) {Arrays.sort(citations);int result 0;for (int i citations.length-1; i >0; i--) {if(citations[i]>citations.length-i)resultcitations.length-i;elsebreak;}return result;} }

内网文件传输新体验,聊天、传输、自定义,一应俱全

Flix 是一款高效、便捷的跨平台局域网文件传输工具&#xff0c;支持 Windows、macOS、Android、iOS 和 Linux 等多种操作系统。它以简洁直观的聊天式界面为特色&#xff0c;让用户能够像发送消息一样轻松地传输文件&#xff0c;无需复杂的设置或登录。Flix 支持大文件和多种格式…

Vue PDF Annotation plugin library online API examples

This article introduces the online version of the ElasticPDF API tutorial for the PDF annotation plug-in library in Vue projects. The API includes ① Export edited PDF data; ② Export annotations json data; ③ Reload old annotations; ④ Change files; ⑤ Se…