刷刷题38(长连接 +切片上传)

前端长连接实现方案总结

以下是前端实现实时通信的常见长连接技术,按性能和复杂度递增排序:


一、短轮询(Short Polling)

  • 原理 ‌:前端通过定时器(如 setInterval)周期性发送 HTTP 请求,服务器立即响应(无论有无新数据)‌。
  • 优点‌:实现简单,浏览器兼容性高‌。
  • 缺点‌:频繁请求浪费带宽和服务器资源,实时性差(延迟取决于轮询间隔)‌。
  • 适用场景‌:数据更新频率低且实时性要求不高的场景(如简单状态监控)‌。

二、长轮询(Long Polling / Comet)

  • 原理‌:前端发起请求后,服务器保持连接直到有新数据或超时,响应后客户端立即重新发起请求‌。
  • 优点‌:相比短轮询减少无效请求,实时性提升‌。
  • 缺点‌:服务器需维护挂起连接,高并发时资源压力大‌。
  • 适用场景‌:中等实时性需求(如简易聊天室)‌。

三、HTTP 长连接(Keep-Alive)

  • 原理 ‌:通过 HTTP/1.1 的 Connection: keep-alive 复用 TCP 连接,支持多个请求复用同一连接‌。
  • 优点‌:减少 TCP 握手次数,提升传输效率‌。
  • 缺点‌:仍基于请求-响应模式,无法实现服务端主动推送‌。
  • 适用场景‌:需要减少连接开销的常规 HTTP 请求‌。

四、Server-Sent Events(SSE)

  • 原理 ‌:基于 HTTP 的单向长连接,服务端通过 EventSource 接口主动推送数据到前端‌。
  • 优点‌:支持自动重连、轻量级协议,兼容性较好‌。
  • 缺点‌:仅支持服务端到客户端的单向通信‌。
  • 适用场景‌:实时数据推送(如新闻推送、股票行情)‌。

五、WebSocket

  • 原理‌:基于 TCP 的全双工协议,通过一次握手建立持久连接,支持客户端和服务端双向实时通信‌。
  • 优点‌:低延迟、高吞吐量,支持二进制和文本数据‌。
  • 缺点‌:需额外处理连接状态(如重连、心跳检测),旧浏览器需降级方案‌。
  • 适用场景‌:高实时性应用(如在线游戏、实时协作工具)‌。

六、方案对比

方案 实时性 带宽消耗 双向通信 适用场景
短轮询 低频数据查询
长轮询 中等实时性需求
HTTP 长连接 高频次常规请求
SSE 单向 服务端单向推送
WebSocket 极高 全双工实时交互

一、为什么需要切片上传?

  1. 解决大文件传输痛点

    • 网络稳定性‌:避免因单次传输失败导致整个文件重传。
    • 性能优化‌:分片并行上传可充分利用带宽,缩短总耗时。
    • 断点续传‌:记录已上传分片,支持中断后恢复上传。
    • 服务器兼容性‌:绕过服务器对单文件大小的限制(如 Nginx 默认限制 1MB)。

二、切片上传的核心实现步骤

1. ‌文件分片(File Chunking)

  • 前端切片方式‌:
ini 复制代码
const chunkSize = 2 * 1024 * 1024; // 每片 2MB
const chunks = [];
let start = 0;
while (start < file.size) {
  const chunk = file.slice(start, start + chunkSize);
  chunks.push(chunk);
  start += chunkSize;
}
  • 分片大小选择‌:

    • 过小(如 100KB):分片过多,增加请求和管理开销。
    • 过大(如 10MB):失去分片意义,难以断点续传。
    • 建议:1~5MB,根据实际网络条件动态调整。

2. ‌分片唯一标识(Hash)

  • 生成文件唯一标识‌:

    • 使用 文件名 + 文件大小 + 最后修改时间 作为标识(简单但可能冲突)。

    • 计算文件哈希‌(更可靠,但耗时):

csharp 复制代码
const hash = await calculateFileHash(file); // 使用 SparkMD5 等库
  • 分片命名规则‌:

    • 格式:{hash}-{index}(如 a3c8b1d2-0)。
    • 服务端通过 hash 合并所有分片。

3. ‌并发控制(Concurrency Control)

  • 浏览器并发限制‌:Chrome 同域名限制 6 个并发请求。
  • 实现并发队列‌:
javascript 复制代码
const maxConcurrency = 3; // 控制并发数
const uploadChunk = async (chunk, index) => { /* 上传逻辑 */ };

// 使用 Promise.all 控制并发
const chunksToUpload = chunks.map((chunk, index) => ({ chunk, index }));
while (chunksToUpload.length > 0) {
  const batch = chunksToUpload.splice(0, maxConcurrency);
  await Promise.all(batch.map(({ chunk, index }) => uploadChunk(chunk, index)));
}

4. ‌断点续传(Resumable Upload)

  • 前端记录已上传分片‌:

    • 使用 localStorageIndexedDB 存储已上传的分片索引。
  • 服务端校验分片状态‌:

    • 上传前先请求接口检查哪些分片已上传(根据分片 hash)。
    • 示例接口:
ini 复制代码
// 请求:GET /upload/check?hash=a3c8b1d2
// 响应:{ uploadedChunks: [0, 1, 2] }

5. ‌分片上传与合并

  • 分片上传接口‌:

    • 使用 FormData 上传分片数据:
go 复制代码
const formData = new FormData();
formData.append('chunk', chunk);
formData.append('hash', hash);
formData.append('index', index);
await axios.post('/upload/chunk', formData);

服务端合并文件‌:

  • 按分片索引顺序合并所有分片(避免乱序导致文件损坏)。
  • 示例(Node.js):
ini 复制代码
const mergeChunks = (hash, totalChunks) => {
  const chunkPaths = Array.from({ length: totalChunks }, (_, i) => `./temp/${hash}-${i}`);
  const writeStream = fs.createWriteStream(`./files/${hash}`);
  chunkPaths.forEach(path => {
    const data = fs.readFileSync(path);
    writeStream.write(data);
    fs.unlinkSync(path); // 删除临时分片
  });
  writeStream.end();
};

6. ‌错误处理与重试机制

  • 分片上传失败重试‌:

    • 为每个分片设置重试次数(如 3 次),采用指数退避策略。
    • 示例:
javascript 复制代码
const uploadWithRetry = async (chunk, index, retries = 3) => {
  try {
    await uploadChunk(chunk, index);
  } catch (err) {
    if (retries > 0) {
      await new Promise(resolve => setTimeout(resolve, 1000 * (4 - retries)));
      return uploadWithRetry(chunk, index, retries - 1);
    } else {
      throw err;
    }
  }
};
  • 全局错误监控‌:

    • 监听 unhandledrejection 事件捕获未处理的 Promise 错误。

7. ‌上传进度监控

  • 计算总进度‌:
ini 复制代码
let uploadedSize = 0;
const totalSize = file.size;

// 每个分片上传成功后更新进度
uploadedSize += chunk.size;
const progress = Math.round((uploadedSize / totalSize) * 100);
  • 实时展示进度条‌:

    • 使用第三方库(如 axiosonUploadProgress)或自定义事件。

三、扩展优化点(加分项)

  1. 动态分片大小‌:根据网络速度调整分片大小(如高速网络用 5MB,低速用 1MB)。
  2. 文件秒传‌:服务端通过文件哈希判断是否已存在相同文件,直接跳过上传。
  3. 浏览器空闲时段上传 ‌:使用 requestIdleCallback 在空闲时上传分片。
  4. 压缩分片 ‌:对图片/视频分片进行压缩(如 canvas.toBlob())。
  5. 分片哈希校验‌:上传分片后,服务端校验分片哈希,防止传输损坏。

"大文件切片上传的核心目标是提升传输可靠性和用户体验。关键点包括:

  1. 合理分片 ‌:根据文件大小动态分片(通常 1-5MB),利用 Blob.slice 切割文件;
  2. 唯一标识‌:通过文件哈希或元数据标识分片,确保服务端正确合并;
  3. 并发控制‌:限制并行请求数,避免触发浏览器并发限制;
  4. 断点续传‌:结合本地存储和服务端校验,实现中断后快速恢复;
  5. 错误重试‌:对失败分片自动重试,采用指数退避策略;
  6. 分片校验 ‌:前后端协同验证分片完整性(如哈希比对)。
    此外,还可以优化分片大小、实现秒传和动态进度提示等。"
相关推荐
Jiude29 分钟前
UnoCSS presetWind4() 背景色使用 color-mix() 的原因及解决方案
前端·css
无名之逆1 小时前
Hyperlane:Rust 生态中的轻量级高性能 HTTP 服务器库,助力现代 Web 开发
服务器·开发语言·前端·后端·http·面试·rust
范哥来了1 小时前
python web开发django库安装与使用
前端·python·django
烛阴1 小时前
JavaScript 的 “new Function”:你不知道的黑魔法,让代码更灵活!
前端·javascript
ConardLi2 小时前
发布第五天,我的开源项目突破 1.7 K Star!
前端·javascript·人工智能
Moment2 小时前
京东一面:postMessage 如何区分不同类型的消息 🤪🤪🤪
前端·javascript·面试
鱼樱前端2 小时前
🔥 Vue2 vs Vue3 的 h 函数终极指南:从入门到源码级深度解析
前端·vue.js
独行soc2 小时前
2025年渗透测试面试题总结-某四字大厂面试复盘 一面(题目+回答)
网络·python·科技·面试·职场和发展·红蓝攻防
Moment2 小时前
💯 铜三铁四,我收集整理了这些大厂面试场景题 (一)
前端·后端·面试
小杨xyyyyyyy2 小时前
Mysql - 日志相关问题
数据库·mysql·面试