开发者日记 – 大文件传输系统开发实录 日期:2023年11月15日 天气:阴
项目背景与需求梳理
作为江苏的一名独立开发者,近期承接了一个企业级文件传输系统项目,核心需求如下:
- 前端:Vue3 + WebUploader(或H5 API)
- 后端:PHP + MySQL(记录分片信息)
- 存储:华为云OBS(对象存储)
技术选型与挑战
1. 上传组件选择
- WebUploader:兼容IE8+,支持分片、断点续传,但需手动封装文件夹解析逻辑。
- H5 File API:现代浏览器支持良好,但IE8/9需Polyfill,且文件夹上传需依赖webkitdirectory(非标准)。 决策:以WebUploader为主,H5作为降级方案,通过User-Agent判断浏览器类型动态切换。
2. 断点续传设计
- 分片存储:将大文件切分为5MB分片,上传时记录已完成的分片序号。
- 进度持久化:
- 前端:使用localStorage或IndexedDB存储临时进度(跨会话)。
- 后端:MySQL表记录文件唯一标识(MD5)、总分片数、已上传分片列表。
- 跨设备恢复:通过文件MD5校验匹配历史记录,从华为云OBS合并已上传分片。
3. 文件夹上传实现
- WebUploader扩展:监听directory事件,递归解析文件夹结构,生成扁平化的文件路径列表(如/parent/child/file.txt)。
- 后端处理:接收路径信息,在华为云OBS中按原路径创建空文件夹(通过putObject设置Content-Type: application/directory)。
核心代码实现
前端(Vue3 + WebUploader)
// src/components/Uploader.vue
import WebUploader from 'webuploader';
import 'webuploader/dist/webuploader.css';
export default {
mounted() {
const uploader = WebUploader.create({
swf: '/path/to/webuploader.swf', // IE8/9兼容
server: '/api/upload',
chunked: true,
chunkSize: 5 * 1024 * 1024, // 5MB分片
formData: {
fileMd5: '', // 通过后端接口预先计算
isDir: false // 标记是否为文件夹
},
files: [] // 存储文件夹结构
});
// 监听文件夹选择(仅现代浏览器)
document.getElementById('filePicker').addEventListener('change', (e) => {
const files = e.target.files;
if (files.length && files[0].webkitRelativePath) {
// 递归解析文件夹
const parseDir = (file, path = '') => {
const fullPath = path + file.name;
if (file.isDirectory) {
// 模拟文件夹上传(实际需后端支持)
return;
}
uploader.addFiles({
name: file.name,
relativePath: fullPath,
size: file.size,
type: file.type
});
};
Array.from(files).forEach(file => parseDir(file));
}
});
// 断点续传:从localStorage加载进度
const resumeData = localStorage.getItem('upload_progress');
if (resumeData) {
const { fileMd5, chunks } = JSON.parse(resumeData);
uploader.option('formData', { fileMd5, isDir: false });
// 跳过已上传的分片(需后端配合校验)
}
// 上传完成合并分片
uploader.on('uploadSuccess', (file, response) => {
if (response.needMerge) {
fetch('/api/merge', {
method: 'POST',
body: JSON.stringify({ fileMd5: response.fileMd5 })
});
}
});
}
};
后端(PHP + MySQL)
// api/upload.php
prepare("INSERT INTO upload_chunks (file_md5, chunk_index, uploaded_at) VALUES (?, ?, NOW())
ON DUPLICATE KEY UPDATE updated_at = NOW()");
$stmt->execute([$fileMd5, $chunkIndex]);
// 上传分片到华为云OBS
$obsClient = new \\OBS\\ObsClient([
'key' => 'your-access-key',
'secret' => 'your-secret-key',
'endpoint' => 'obs.cn-east-3.myhuaweicloud.com'
]);
$obsPath = "uploads/{$fileMd5}/chunk_{$chunkIndex}";
$obsClient->putObject([
'Bucket' => 'your-bucket',
'Key' => $obsPath,
'SourceFile' => $_FILES['file']['tmp_name']
]);
// 检查是否所有分片已上传
$chunksCount = $pdo->query("SELECT COUNT(*) FROM upload_chunks WHERE file_md5 = '{$fileMd5}'")->fetchColumn();
$totalChunks = $_POST['totalChunks']; // 前端传递总分片数
if ($chunksCount === $totalChunks) {
echo json_encode(['needMerge' => true, 'fileMd5' => $fileMd5]);
} else {
echo json_encode(['success' => true]);
}
?>
MySQL表结构
CREATE TABLE upload_chunks (
id INT AUTO_INCREMENT PRIMARY KEY,
file_md5 VARCHAR(32) NOT NULL,
chunk_index INT NOT NULL,
uploaded_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY (file_md5, chunk_index)
);
测试与优化
- IE8:需引入es5-shim和json2.js。
- 文件夹上传:在Chrome中测试webkitRelativePath,IE使用ActiveX模拟(需用户授权)。
- 分片并发上传(WebUploader默认支持3个并发)。
- 华为云OBS启用CDN加速下载。
- 手动终止进程后,重启上传时跳过已完成的分片。
后续计划
今日总结:核心功能已跑通,但IE兼容性和文件夹解析仍需打磨。欢迎大神加入QQ群交流优化方案!
(日记结束)
注:实际项目中需补充安全校验(如文件类型白名单、分片签名防篡改),代码仅为示例框架,需根据业务需求调整。
安装环境
PHP:7.2.14 
调整块大小

NOSQL
NOSQL不需要任何配置,可以直接访问测试 
SQL
创建数据库
您可以直接复制脚本进行创建

配置数据库连接

安装依赖

访问页面进行测试

数据表中的数据

效果预览
文件上传

文件刷新续传
支持离线保存文件进度,在关闭浏览器,刷新浏览器后进行不丢失,仍然能够继续上传 
文件夹上传
支持上传文件夹并保留层级结构,同样支持进度信息离线保存,刷新页面,关闭页面,重启系统不丢失上传进度。 
免费下载示例
点击下载完整示例
网硕互联帮助中心






评论前必须登录!
注册