在现代 Web 开发中,文件上传是常见的需求。对于大文件上传场景(如视频、日志、镜像等),传统单次上传方式存在性能瓶颈和失败风险。为了解决这一问题,mldong 快速开发框架 引入了 分片上传(Multipart Upload) 模块,通过将大文件拆分成多个小块进行上传,提升稳定性和用户体验。
本文将从整体架构、接口设计、前端组件实现、后端服务支撑等多个维度,全面解析 mldong 分片上传模块的设计与实现。
一、分片上传的整体流程
分片上传的核心思想是:将一个大文件分割成多个小片段分别上传,最后在服务器上合并所有片段,形成完整的文件。其核心步骤如下:
- 初始化分片上传任务
- 依次上传每个分片
- 完成上传并合并文件
- 取消上传或失败处理
我们可以使用 PlantUML 绘制流程图来清晰表达整个交互过程:
二、接口设计(后端)
1. 初始化分片上传
@PostMapping("/sys/fileInfo/initiateMultipartUpload")
public CommonResult<Dict> initiateMultipartUpload(@RequestBody FileInfoParam param);
- 功能说明:创建一个上传会话,返回
uploadId和fileInfoId - 请求参数:
originalFilename: 原始文件名objectType: 文件类型标识contentType: MIME 类型size: 文件总大小
- 响应示例:
{
"code": 0,
"msg": "成功",
"data": {
"fileInfoId": "1938914498327797762",
"uploadId": "685fca7635f9b439503acdb2"
}
}
2. 上传单个分片
@PostMapping("/sys/fileInfo/uploadPart")
public CommonResult<?> uploadPart(MultipartFile file, @RequestParam Integer partNumber, @RequestParam Long fileInfoId);
- 功能说明:上传指定序号的分片
- 请求参数:
partNumber: 分片序号(从 1 开始)fileInfoId: 文件 ID,在第一步中返回file: 当前分片数据
- 响应示例:
{
"code": 0,
"msg": "成功",
"data": null
}
3. 完成分片上传
@PostMapping("/sys/fileInfo/completeMultipartUpload")
public CommonResult<Dict> completeMultipartUpload(@RequestBody FileInfoParam param);
- 功能说明:通知服务端合并所有分片
- 请求参数:
- fileInfoId: 文件 ID,在第一步中返回
- 响应示例:
{
"code": 0,
"msg": "成功",
"data": {
"fullUrl": "/api/uploadfiles/mldong/202506/1938914498327797762.pdf",
"url": "mldong/202506/1938914498327797762.pdf",
"fileInfoId": "1938914498327797762"
}
}
4. 取消分片上传
@PostMapping("/sys/fileInfo/abortMultipartUpload")
public CommonResult<?> abortMultipartUpload(@RequestBody FileInfoParam param);
- 功能说明:中断当前上传过程,清理服务器上的临时文件
- 请求参数:
fileInfoId: 文件 ID,在第一步中返回
- 响应示例:
{
"code": 0,
"msg": "成功",
"data": null
}
三、前端组件实现(Vue + Ant Design Vue)
在前端,我们基于 Ant Design Vue 的 Upload 组件 进行封装,实现了对分片上传的支持,并提供了良好的交互体验。
1. 核心组件结构
<template>
<Upload
v-model:file-list="fileList"
:action="action"
:before-upload="beforeUpload"
@change="handleChange"
@remove="handleRemove"
>
<!-- 自定义按钮 -->
<Button :loading="isUploading">上传文件</Button>
</Upload>
<!-- 分片进度条 -->
<div v-if="isUploading" class="upload-progress">
<div class="progress-bar" :style="{ width: `${uploadProgress}%` }"></div>
<div class="chunk-item" v-for="i in totalChunks" :key="i" :class="{ completed: i <= currentChunk }"></div>
</div>
</template>
2. 分片上传逻辑封装
(1) 初始化上传会话
const initializeChunk = async (file: File) => {
const initData = {
contentType: file.type,
originalFilename: file.name,
objectType: props.objectType,
size: file.size.toString(),
};
return await initiateMultipartUpload(initData);
};
(2) 切分文件为多个分片
const createFileChunks = (file: File) => {
const chunks = [];
let start = 0;
let index = 0;
totalChunks.value = Math.ceil(file.size / props.chunkSize);
while (start < file.size) {
chunks.push({
chunk: file.slice(start, start + props.chunkSize),
index,
});
start += props.chunkSize;
index++;
}
return chunks;
};
(3) 上传每个分片
const uploadChunk = async (chunk: Blob, filename: string, uploadId: string, fileInfoId: string, index: number) => {
await uploadPart({
partNumber: index + 1,
uploadId,
fileInfoId,
file: new File([chunk], filename),
});
currentChunk.value = index + 1;
uploadProgress.value = Math.round(((index + 1) / totalChunks.value) * 100);
};
(4) 完成上传并合并文件
const completeRes = await completeMultipartUpload({
uploadId: uploadId.value,
fileInfoId,
});
3. 组件使用样例
样例是在vben5框架下的,这里简单的配置
主要是:multipart设置为true,则启用分片上传。
{
fieldName: 'attachment1',
label: '附件',
component: 'Upload',
help: '分片上传',
componentProps: {
listType: 'text',
multipart: true,
},
formItemClass: 'col-span-12',
detailSpan: 12,
}
四、优势总结
| 特性 | 描述 |
|---|---|
| ✅ 支持大文件上传 | 突破浏览器上传限制,支持 GB 级文件 |
| ⚙️ 断点续传基础支持 | 分片机制天然支持断点续传扩展 |
| 📈 实时进度展示 | 提供分片级和总体进度条可视化 |
| 🔄 失败自动中断 | 上传异常自动调用 abortMultipartUpload 清理资源 |
| 📦 易于集成 | 基于 Vue + Ant Design Vue 封装,开箱即用 |
五、结语
随着企业数字化转型的加速,文件上传作为系统交互的重要环节,其稳定性与效率至关重要。mldong 快速开发框架 中的分片上传模块,不仅解决了大文件上传的技术难题,还通过前后端协同设计,实现了良好的用户体验与可维护性。
未来,我们将继续优化该模块,计划引入以下特性:
- ✅ 分片缓存与断点续传
- ✅ 多线程并发上传
- ✅ 秒传支持(MD5校验)
- ✅ 跨域支持与安全控制
如果你正在寻找一套高效、易用、可扩展的文件上传解决方案,欢迎尝试 mldong!
📌 项目地址
目前放在【系统管理】->【岗位管理】的第一个【附件】字段上。
注:演示站非只是apifox的模拟接口,非真实上传,如要完整体验,需要下载前端端工程体验。