在能源化工行业,管道巡检日志往往包含大量高清图片、视频和传感器数据,单个日志文件经常超过20GB。传统基于WebUploader的方案在传输这类超大附件时面临三大痛点:
以某石化企业的实际案例为例,其每日产生的管道巡检数据约500GB,原系统在传输过程中平均失败率达15%,每次中断需要重新上传,严重影响了巡检效率。
采用分层设计模式,各层职责明确:
code复制前端传输层(Vue3)
↑↓ WebSocket/HTTP
业务逻辑层(Spring Boot)
↑↓ Netty
存储适配层(本地/OBS/MinIO)
↑
加密服务层(SM4/AES)
| 组件类型 | 选型方案 | 选型理由 |
|---|---|---|
| 前端框架 | Vue3 + TypeScript | 更好的类型支持和性能优化 |
| 通信协议 | WebSocket + HTTP | 双协议保障兼容性 |
| 后端框架 | Spring Boot 2.7 | 企业级开发生态完善 |
| 网络库 | Netty 4.1 | 高并发处理能力 |
| 加密算法 | SM4(国密) | 满足行业合规要求 |
java复制// 分块大小动态调整算法
public int calculateChunkSize(long fileSize, long availableMemory) {
int baseSize = 5 * 1024 * 1024; // 5MB基础分块
int maxChunks = 1000; // 最大分块数限制
// 根据文件大小和内存情况动态调整
return (int) Math.min(
baseSize,
Math.max(
fileSize / maxChunks,
1024 * 1024 // 最小1MB
)
);
}
使用Redis存储分块上传状态:
java复制// Redis数据结构设计
{
"upload:file123": {
"fileName": "pipe_inspection_2023.log",
"fileSize": 21474836480,
"chunkSize": 5242880,
"uploadedChunks": [0,1,2,3,4,5],
"md5": "a1b2c3d4e5f6...",
"expire": 86400
}
}
javascript复制// 浏览器能力检测
function checkBrowserCapabilities() {
return {
// 基础能力
fileAPI: !!window.File && !!window.FileReader,
blobSupport: !!window.Blob,
formData: !!window.FormData,
// 高级特性
webWorker: !!window.Worker,
webSocket: !!window.WebSocket,
// 国产浏览器特殊检测
isUOS: navigator.userAgent.includes('UOS'),
isKylin: navigator.userAgent.includes('Kylin')
};
}
java复制// 动态SQL生成器
public class DynamicSQLBuilder {
public String buildInsertSQL(String tableName, Map<String, Object> data) {
switch(databaseType) {
case "dm": // 达梦
return buildDmSQL(tableName, data);
case "kingbase": // 人大金仓
return buildKingbaseSQL(tableName, data);
default:
return buildStandardSQL(tableName, data);
}
}
private String buildDmSQL(String tableName, Map<String, Object> data) {
// 达梦特殊语法处理
}
}
javascript复制// SM4分块加密
async function encryptChunk(chunk, key, iv) {
const wordArray = CryptoJS.lib.WordArray.create(chunk);
return CryptoJS.SM4.encrypt(wordArray, key, { iv }).toString();
}
java复制public class SM4Decryptor {
public byte[] decrypt(byte[] encrypted, byte[] key, byte[] iv) {
Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE,
new SecretKeySpec(key, "SM4"),
new IvParameterSpec(iv));
return cipher.doFinal(encrypted);
}
}
采用分层加密策略:
java复制// 线程池配置
@Bean
public ThreadPoolTaskExecutor uploadExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("upload-");
return executor;
}
采用零拷贝技术处理大文件:
java复制public void transferWithZeroCopy(Path source, Path target) {
try (FileChannel in = FileChannel.open(source);
FileChannel out = FileChannel.open(target, CREATE, WRITE)) {
in.transferTo(0, in.size(), out);
}
}
| 组件 | 最低配置 | 推荐配置 |
|---|---|---|
| 应用服务器 | 4核8G | 8核16G |
| 数据库 | 4核8G 100G存储 | 8核16G 500G SSD |
| Redis | 2核4G | 4核8G |
Docker Compose示例:
yaml复制version: '3'
services:
app:
image: myapp:1.0
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
volumes:
- /data/uploads:/app/uploads
redis:
image: redis:6
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
redis_data:
| 方案 | 首次上传 | 断点续传 | CPU占用 |
|---|---|---|---|
| 传统方案 | 45分钟 | 45分钟 | 85% |
| 本方案 | 32分钟 | 8分钟 | 65% |
| 环境 | 上传成功率 | 下载成功率 |
|---|---|---|
| Windows+Chrome | 99.8% | 99.9% |
| 统信UOS | 99.5% | 99.7% |
| 银河麒麟 | 99.2% | 99.5% |
问题现象:上传到90%时网络断开
解决步骤:
典型报错:"ClassNotFoundException: SM4Cipher"
解决方案:
某大型炼化企业部署本方案后:
java复制public class ScadaIntegration {
public void sendToScada(FileData data) {
// 转换为OPC UA格式
OpcUaMessage message = convertToOpcUa(data);
opcClient.send(message);
}
}
python复制# Python分析服务示例
def analyze_inspection_data(file_path):
import pandas as pd
from tensorflow import keras
model = keras.models.load_model('pipe_model.h5')
data = pd.read_parquet(file_path)
return model.predict(data)
在具体实施时,建议先进行小规模试点,重点验证:
对于特大型文件(50GB+),可以考虑增加以下优化: