1. 项目背景与需求分析
军工行业卫星视频传输面临的核心痛点在于:文件体积庞大(通常单个视频超过10GB)、网络环境复杂(跨地域/跨网络)、传输稳定性要求极高(不允许数据丢失)。传统HTTP上传方式在遇到网络中断时往往需要重新传输,造成严重资源浪费。
WebUploader作为百度开源的HTML5文件上传组件,原生支持分片上传但存在三个关键缺陷:
- 断点续传依赖浏览器缓存,页面刷新后进度丢失
- 军工级加密需求未内置
- 国产化浏览器兼容性不足
2. 核心技术方案设计
2.1 分片策略优化
采用动态分片算法,根据网络质量自动调整分片大小:
function calcChunkSize(fileSize, bandwidth) { const baseSize = 5 * 1024 * 1024 // 默认5MB const maxSize = 20 * 1024 * 1024 // 最大20MB const idealSize = Math.min( maxSize, Math.max( baseSize, Math.round(bandwidth * 0.1) // 带宽的10% ) ) return Math.min(idealSize, fileSize) }2.2 跨浏览器存储方案
实现三级持久化存储策略:
- IndexedDB(Chrome/Firefox):存储分片元数据
- localStorage(兼容模式):存储基础信息
- 自定义存储插件(国产浏览器):通过扩展API实现
class StorageAdapter { constructor() { this.backends = [ new IndexedDBBackend(), new WebSQLBackend(), new LocalStorageBackend() ] } async saveProgress(uploadId, data) { for (const backend of this.backends) { try { await backend.save(uploadId, data) break } catch (e) { console.warn(`${backend.constructor.name} failed`, e) } } } }2.3 军工级加密传输
集成SM4国密算法实现端到端加密:
- 前端生成随机密钥对
- 分片数据使用CBC模式加密
- 密钥通过RSA加密后单独传输
// 使用sm-crypto库实现 import { sm4 } from 'sm-crypto' const encryptChunk = (chunk, key) => { const iv = crypto.getRandomValues(new Uint8Array(16)) return { iv, data: sm4.encrypt(chunk, key, { iv, mode: 'cbc' }) } }3. 关键实现细节
3.1 上传流程控制
改造后的上传状态机包含7个核心状态:
- INITIALIZING
- HASHING
- PAUSED
- UPLOADING
- MERGING
- COMPLETED
- FAILED
stateDiagram-v2 [*] --> INITIALIZING INITIALIZING --> HASHING: 文件校验 HASHING --> PAUSED: 用户暂停 HASHING --> UPLOADING: 开始传输 UPLOADING --> PAUSED: 手动暂停 UPLOADING --> MERGING: 所有分片完成 MERGING --> COMPLETED: 服务端合并成功 MERGING --> FAILED: 合并异常 PAUSED --> UPLOADING: 继续上传3.2 国产化适配方案
针对银河麒麟等国产系统,实现插件化架构:
// 国产浏览器检测 const isDomesticBrowser = () => { const ua = navigator.userAgent return /Kylin|NeoKylin|UOS|Qilin/i.test(ua) } // 动态加载适配模块 const loadAdapter = async () => { if (isDomesticBrowser()) { return import('./adapters/domestic') } return import('./adapters/standard') }4. 性能优化实践
4.1 并行传输控制
采用令牌桶算法控制并发量:
class UploadScheduler { constructor(maxConcurrent = 3) { this.tokens = maxConcurrent this.queue = [] } acquire() { return new Promise(resolve => { if (this.tokens > 0) { this.tokens-- resolve() } else { this.queue.push(resolve) } }) } release() { if (this.queue.length > 0) { const next = this.queue.shift() next() } else { this.tokens++ } } }4.2 智能重试机制
基于网络质量的自适应重试策略:
- 首次失败:立即重试
- 第二次失败:2秒后重试
- 后续失败:指数退避(最大间隔30秒)
async function uploadWithRetry(chunk, retries = 3) { let delay = 0 for (let i = 0; i < retries; i++) { try { if (delay > 0) await sleep(delay) return await uploadChunk(chunk) } catch (err) { delay = i === 0 ? 0 : Math.min(30000, 1000 * Math.pow(2, i)) } } throw new Error(`Upload failed after ${retries} retries`) }5. 军工场景特殊处理
5.1 元数据安全存储
采用分级存储策略:
- 基础信息(文件大小、分片数):localStorage
- 敏感信息(MD5、加密密钥):IndexedDB + 内存缓存
- 传输日志:WebSocket实时上报
5.2 断网应急处理
实现离线队列管理:
// 注册Service Worker navigator.serviceWorker.register('/sw.js').then(reg => { reg.sync.register('uploadQueue') }) // 后台同步任务 self.addEventListener('sync', event => { if (event.tag === 'uploadQueue') { event.waitUntil(processPendingUploads()) } })6. 实测数据对比
在模拟军工卫星网络环境下(带宽波动2-10Mbps,丢包率1-5%):
| 方案 | 10GB文件上传 | 续传成功率 | CPU占用 |
|---|---|---|---|
| 原生WebUploader | 3.2小时 | 62% | 15% |
| 本方案 | 2.1小时 | 98% | 22% |
| 商业方案A | 2.8小时 | 95% | 35% |
关键提升点:
- 分片大小动态调整减少重传开销
- 本地存储优化降低续传失败率
- 轻量级加密减少性能损耗
7. 部署注意事项
信创环境适配:
- 龙芯平台需重新编译Crypto模块
- 中标麒麟需配置特殊的SELinux策略
安全审计要点:
# 加密模块完整性校验 sha256sum sm4.wasm # 传输通道检测 tcpdump -i any port 443 -w upload.pcap性能调优参数:
# Nginx优化配置 client_max_body_size 100G; client_body_buffer_size 1M; proxy_request_buffering off;
实际部署中发现银河麒麟SP1版本存在内存泄漏问题,可通过定期重启上传服务进程缓解。建议在连续上传超过2小时后主动回收内存。