LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

前端大文件上传的时候,采用切片上传的方式,如果断网了,应该如何处理

zhenglin
2026年1月10日 15:4 本文热度 504
我们前端在大文件上传的时候基本上都会考虑切片上传的方式,那么在切片上传的场景中,断网是最常见的异常情况之一,如果想要断网恢复之后,继续上传,就需要通过断点续传机制来处理。刚好公司做了云盘的功能,遇到了这个切片上传的问题,总结一下,分享给大家~


这个问题的核心目标是:断网后不丢失已上传进度,网络恢复后能从断点继续上传,避免重复上传已完成的切片



一、断网检测与状态捕获

首先需要准确检测网络状态变化,以便及时触发中断处理逻辑:

  1. 网络状态监听
    利用浏览器提供的 navigator.onLine 属性和 online/offline 事件监听网络状态:


// 监听网络断开

window.addEventListener('offline', () => {

  console.log('网络已断开,暂停上传');

  pauseUpload(); // 触发上传暂停逻辑

});


// 监听网络恢复

window.addEventListener('online', () => {

  console.log('网络已恢复,尝试继续上传');

  resumeUpload(); // 触发续传逻辑

});

React 结合Hooks来实现
使用 useEffect 进行事件绑定 / 解绑,确保与组件生命周期同步
初始状态通过 navigator.onLine 获取,避免初始值与实际状态不一致

import { useState, useEffect } from 'react';


function NetworkStatus() {

  // 状态管理:是否在线

  const [isOnline, setIsOnline] = useState(navigator.onLine);


  useEffect(() => {

    // 定义事件处理函数

    const handleOnline = () => setIsOnline(true);

    const handleOffline = () => setIsOnline(false);


    // 绑定事件监听

    window.addEventListener('online', handleOnline);

    window.addEventListener('offline', handleOffline);


    // 组件卸载时清除监听(避免内存泄漏)

    return () => {

      window.removeEventListener('online', handleOnline);

      window.removeEventListener('offline', handleOffline);

    };

  }, []); // 空依赖数组:只在组件挂载时执行一次


  return (

    <div>

      <p>网络状态:{isOnline ? '在线' : '离线'}</p>

    </div>

  );

}


  1. 请求层面的异常捕获
    即使网络未完全断开(如弱网超时),单个切片上传请求也可能失败,需在 fetch 或 axios 中捕获异常:

async function uploadChunk(chunk) {

  try {

    const response = await fetch('/upload-chunk', {

      method: 'POST',

      body: chunk.formData,

    });

    if (!response.ok) throw new Error('请求失败');

    return { success: true, chunkIndex: chunk.index };

  } catch (error) {

    console.log(`切片 ${chunk.index} 上传失败`, error);

    return { success: false, chunkIndex: chunk.index };

  }

}



二、断网时的核心处理逻辑

断网后需保存当前上传状态,为后续续传提供依据:

  1. 保存上传进度状态
    将已上传的切片信息、文件元数据等保存到本地存储(如 localStorage 或 IndexedDB,后者更适合大量数据):

代码高亮:

// 定义需要保存的上传状态结构

const uploadState = {

  fileId: 'xxx', // 文件唯一标识(如哈希值)

  fileName: 'large-file.zip',

  totalChunks: 50, // 总切片数

  uploadedChunks: [0, 1, 2, ...], // 已成功上传的切片索引

  chunkSize: 2 * 1024 * 1024, // 切片大小

  lastUploadedChunk: 23, // 最后一次成功上传的切片索引

  fileSize: 100 * 1024 * 1024, // 文件总大小

};


// 保存到 IndexedDB(适合大文件状态)

function saveUploadState(state) {

  return indexedDB.transaction('rw', db.uploadStates, () => {

    db.uploadStates.put(state);

  });

}

  1. 暂停上传队列
    如果使用并发上传(如同时上传3个切片),断网后需终止当前正在进行的请求,并清空等待队列:

let uploadQueue = []; // 等待上传的切片队列

let activeRequests = []; // 当前正在进行的请求


function pauseUpload() {

  // 终止所有活跃请求

  activeRequests.forEach(abortController => abortController.abort());

  // 清空队列(后续续传时重新生成)

  uploadQueue = [];

}

  1. 用户体验提示
    向用户展示明确的状态提示(如“网络已断开,已保存上传进度”),避免用户误以为上传失败或需要重新开始。


三、网络恢复后的续传逻辑

网络恢复后,核心是基于已保存的状态,仅上传未完成的切片

  1. 恢复上传状态
    从本地存储中读取之前保存的 uploadState,确认文件信息和已上传切片:

async function getSavedState(fileId) {

  return indexedDB.transaction('r', db.uploadStates, () => {

    return db.uploadStates.get(fileId);

  });

}

  1. 与服务端校验已上传切片
    为避免本地状态与服务端不一致(如断网时某切片已上传成功但前端未记录),需向服务端查询当前文件已接收的切片:

async function getServerUploadedChunks(fileId) {

  const response = await fetch(`/get-uploaded-chunks?fileId=${fileId}`);

  return response.json(); // 服务端返回已接收的切片索引数组

}

  1. 生成待上传切片队列
    对比本地已上传切片和服务端返回的切片,计算出未上传的切片,生成新的上传队列:

代码高亮:

async function resumeUpload(fileId) {

  // 1. 读取本地保存的状态

  const localState = await getSavedState(fileId);

  if (!localState) {

    console.log('无保存的上传状态,需重新上传');

    return;

  }


  // 2. 向服务端校验已上传切片

  const serverChunks = await getServerUploadedChunks(fileId);


  // 3. 计算未上传的切片(取本地和服务端的并集,排除已上传的)

  const allChunks = Array.from({ length: localState.totalChunks }, (_, i) => i);

  const uploadedChunks = [...new Set([...localState.uploadedChunks, ...serverChunks])];

  const pendingChunks = allChunks.filter(index => !uploadedChunks.includes(index));


  // 4. 重新发起上传(仅上传未完成的切片)

  uploadPendingChunks(localState, pendingChunks);

}

  1. 继续上传未完成切片
    按原有的并发策略(如同时上传3个),逐个上传 pendingChunks 中的切片,并实时更新本地状态和服务端记录。


四、额外的可靠性保障

  1. 文件唯一标识
    用文件内容的哈希值(如 md5sha256)作为 fileId,确保即使文件名相同但内容不同时,也能正确区分上传进度。

  2. 切片上传的幂等性
    服务端需支持重复上传同一切片(即多次上传同一 fileId + chunkIndex 时,不会重复存储,直接返回成功),避免网络抖动导致的重复上传问题。

  3. 定期保存状态
    不仅在断网时保存状态,每成功上传一个切片后都更新本地存储,降低因页面刷新/关闭导致的进度丢失风险。

  4. 超时重试机制
    网络恢复后,若首次续传失败(如服务端暂时不可用),可设置有限次数的重试(如最多重试3次),进一步提升可靠性。


总结

断网处理的核心是 “状态保存-校验-续传” 闭环:

  1. 断网时通过事件监听捕获异常,保存已上传进度到本地;

  2. 网络恢复后,结合本地状态和服务端校验,确定未上传的切片;

  3. 仅上传未完成的切片,最终完成整个文件的上传和合并。

总结一下,以免遗忘


参考文章:原文链接


该文章在 2026/1/10 15:04:45 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved