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

JS—大文件上传

个人博客:haichenyi.com。感谢关注

一. 目录

  • 一–目录
  • 二–分片上传
  • 三–生成文件唯一标识(文件哈希)​
  • 四–断点续传 & 秒传
  • 五–分片上传(并发控制)​
  • 六–服务端合并分片​
  • 七–优化​
  • 八–总结​

  大文件上传的核心痛点是:文件过大,用户网络环境不稳定,服务器压力过大,容易中断,用户体验极差。只要解决这几个问题就行了。其实,最重要的一个问题就是文件过大。文件太大了,我们就分成几份上传就行了。这就是分片。

大文件上传的核心流程​
​​1. ​​前端分片​​ → 2. ​​计算文件唯一标识​​ → 3. ​​上传分片​​ → 4. ​​服务端合并分片​​ → 5. ​​完整性校验​

二. 分片上传

  将大文件分割成多个固定的小文件,减少单次请求的压力。举个栗子:100M的文件,分成10份,每个10M,这样就可以解决问题。核心代码如下

//主要就是File.slice
function createFileChunks(file, chunkSize = 10 * 1024 * 1024) {
    //分片数组
    const chunks = []
    //文件总大小
    const fileSize = file.size
    let start = 0
    while (start < fileSize) {
        //单个分片
        let chunk = {
            //文件数据
            chunk: file.slice(start, start + fileSize),
            //索引,用于文件合并时的顺序
            index: chunks.length
        }
        chunks.push(chunk)
        start += chunkSize
    }
    return chunks
}

三. 生成文件唯一标识(文件哈希)

  使用文件内容生成唯一标识,用于标识文件,实现秒传和断点续传。代码如下

function calculateFileHash(file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        const spark = new SparkMD5.ArrayBuffer();
        reader.readAsArrayBuffer(file);
        reader.onload = (e) => {
            spark.append(e.target.result);
            const hash = spark.end();
            resolve(hash);
        };
    })
}

四. 断点续传 & 秒传

秒传: 在上传之前,检查服务端是否存在已经有相同哈希值的文件,有则跳过,没有,则上传
断点续传: 上传前,检查已经上传的分片列表,跳过已上传的分片

五. 分片上传(并发控制)

使用Promise池控制并发数(如同时上传3个分片),避免浏览器阻塞。

async function uploadChunks(chunks, fileHash, concurrency = 3) {
  const pool = new Set(); // 并发池
  for (const { chunk, index } of chunks) {
    const formData = new FormData();
    formData.append('chunk', chunk);
    formData.append('hash', fileHash);
    formData.append('index', index);

    const task = fetch('/api/upload-chunk', {
      method: 'POST',
      body: formData,
    }).then(() => {
      pool.delete(task);
    });

    pool.add(task);
    if (pool.size >= concurrency) {
      await Promise.race(pool); // 等待任意任务完成
    }
  }
  await Promise.all(pool); // 等待剩余任务完成
}

六. 服务端合并分片

当文件分片全都上传完成之后,前端触发文件合并逻辑,服务端合并文件。我们上传文件分片的时候上传了文件的hash值和索引。直接按照文件的hash值过滤出同一个文件的分片,然后按照索引,一次写入file即可。

七. 优化​

  1. 分片上传进度显示​。
  2. 错误重试机制​,为每个分片上传添加重试逻辑(最多3次)。
  3. 浏览器本地持久化,使用localStorage或IndexedDB保存上传状态,页面刷新后恢复。

八. 总结

大文件上传的核心在于​​分治策略​​:

  • 分片​​:将大问题拆解为小任务
  • 断点续传​​:增强容错能力
  • 并发控制​​:平衡速度与稳定性

相关文章:

  • AI与无人驾驶汽车:如何通过机器学习提升自动驾驶系统的安全性?
  • vs code Cline 编程接入Claude 3.7的经济方案,且保持原生接口能力
  • css 练习01
  • [dp12_回文子串] 最长回文子串 | 分割回文串 IV
  • Kotlin作用域函数
  • MyBatis-Plus笔记(下)
  • 龙虎榜——20250414
  • TLS协议四次握手原理详解,密钥套件采用DH密钥交换算法
  • Video Encoder:多模态大模型如何看懂视频
  • 【HFP】蓝牙 HFP 协议状态通知机制研究
  • 数据结构初阶:双向链表
  • 常见的 14 个 HTTP 状态码详解
  • MySQL函数
  • 鸿蒙开发-布局
  • CTF-SQL注入
  • Go:接口
  • 大风频繁,疾风气象大模型竞速:AI如何提前10天预测极端天气?
  • Spark SQL
  • C++ 用红黑树封装map/set
  • PD-1 功能性抗体知多少
  • 85岁眼科专家、武汉大学人民医院原眼科主任喻长泰逝世
  • 长沙岳麓警方通报“女子疑被性侵”:正在进一步侦办
  • 专业纯粹,安静温暖,上海古籍书店明日重新开张
  • 接下来上海很热闹,天后天团轮番来开演唱会
  • 五一抢票崩了?12306:及时消除短暂延迟现象,系统平稳度过今日售票高峰
  • 体坛联播|逆转好戏还差一点,多特蒙德、维拉昂首告别欧冠