1. 大文件断点续传系统设计与实现
最近在项目中遇到了一个棘手的需求:需要实现一个支持20G大文件上传、保留文件夹层级结构、支持断点续传的文件上传系统。经过一番折腾,终于搞定了这个方案,现在把完整实现过程分享给大家。
这个方案基于Vue3+原生JS+SpringBoot实现,支持AES/SM4双加密模式,兼容IE9+及所有现代浏览器。下面我会从前端到后端详细讲解每个环节的实现要点。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 前端实现方案
2.1 项目初始化与基础配置
首先创建一个Vue3项目作为前端基础:
bash复制npm init vue@latest file-uploader
cd file-uploader
npm install
这里我选择使用原生JS实现WebUploader功能,而不是直接使用现成的上传组件,这样可以更灵活地控制上传过程。
2.2 核心上传组件实现
创建FileUploader.vue组件,这是整个上传功能的核心:
html复制<template>
<div class="uploader-container">
<div id="filePicker">选择文件</div>
<div class="file-list"></div>
<div class="statusBar">
<div class="progress">
<div class="percentage"></div>
<div class="text">0%</div>
</div>
<button class="btn btn-pause" @click="togglePause">暂停</button>
<button class="btn btn-resume" @click="toggleResume" style="display:none">继续</button>
</div>
</div>
</template>
2.3 WebUploader初始化与配置
在组件中初始化WebUploader是关键步骤:
javascript复制setupUploader() {
const _this = this;
const uploader = WebUploader.create({
auto: false, // 不自动上传
swf: 'https://cdn.jsdelivr.net/npm/webuploader@0.1.1/dist/Uploader.swf', // Flash文件地址
server: '/api/upload/chunk', // 上传接口地址
pick: {
id: '#filePicker',
multiple: true,
directory: true // 启用文件夹选择
},
chunked: true, // 开启分片上传
chunkSize: 5 * 1024 * 1024, // 每片5MB
threads: 3, // 并发上传线程数
formData: {
encryptType: 'AES' // 默认加密方式
},
accept: {
title: 'All',
extensions: '*',
mimeTypes: '*'
},
duplicate: true // 允许重复上传
});
// 文件加入队列事件
uploader.on('fileQueued', function(file) {
_this.addFileToList(file);
});
// 上传进度事件
uploader.on('uploadProgress', function(file, percentage) {
_this.updateProgress(file, percentage);
});
// 上传成功事件
uploader.on('uploadSuccess', function(file, response) {
_this.uploadComplete(file, response);
});
// 上传前添加额外参数
uploader.on('uploadBeforeSend', function(object, data, headers) {
data.relativePath = object.file.relativePath || '';
data.fullPath = object.file.fullPath || '';
data.isDir = object.file.isDir || false;
});
this.uploader = uploader;
}
2.4 文件列表与进度展示
实现文件列表和进度展示功能:
javascript复制addFileToList(file) {
const fileList = document.querySelector('.file-list');
const fileItem = document.createElement('div');
fileItem.id = file.id;
fileItem.className = 'file-item';
const isFolder = file.name.indexOf('.') === -1 && file.type === '' && file.webkitRelativePath;
fileItem.innerHTML = `
<div class="file-info">
<span class="file-name">${isFolder ? '📁 ' + file.name : '📄 ' + file.name}</span>
<span class="file-size">${this.formatFileSize(file.size)}</span>
</div>
<div class="file-progress"></div>
<div class="file-status">等待上传...</div>
`;
fileList.appendChild(fileItem);
// 保存文件路径信息
if (file.source && file.source._relativePath) {
file.relativePath = file.source._relativePath;
file.fullPath = file.source._file.webkitRelativePath || '';
}
}
2.5 断点续传实现原理
断点续传的核心逻辑:
- 文件分片:将大文件分割成多个小片段(默认5MB)
- 分片标识:为每个分片生成唯一ID
- 上传前检查:每次上传前先检查分片是否已存在
- 记录上传状态:后端记录已上传的分片信息
- 断点恢复:中断后重新上传时,跳过已上传的分片
3. 后端实现方案
3.1 SpringBoot项目配置
后端使用SpringBoot框架,主要依赖:
xml复制<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>sprin
