当前位置: 代码网 > it编程>编程语言>Java > Spring Boot实现分片上传、断点续传与进度条功能

Spring Boot实现分片上传、断点续传与进度条功能

2026年02月28日 Java 我要评论
spring boot 实现分片上传、断点续传与进度条# spring boot 实现分片上传、断点续传与进度条 ## —— 支持 minio / rustfs / seaweedfs 可配置切换在

spring boot 实现分片上传、断点续传与进度条

# spring boot 实现分片上传、断点续传与进度条  
## —— 支持 minio / rustfs / seaweedfs 可配置切换
在大文件上传场景下,传统单次上传存在明显问题:
- 文件过大,失败后需要整体重传
- 网络不稳定,用户体验差
- 无法展示上传进度
本文基于 **spring boot**,实现一套**生产可用**的大文件上传方案,支持:
- 分片上传
- 断点续传
- 上传进度查询
- minio / rustfs / seaweedfs / 本地存储
- 通过 yml 配置文件切换存储类型
---
## 一、整体架构设计
系统整体采用「接口隔离 + 策略模式」设计:

controller ↓ uploadservice ↓ storageservice(统一抽象) ↓ minio / rustfs / seaweedfs / local

**核心思想:上传逻辑与底层存储解耦。**
---
## 二、统一配置设计
### 1. 存储类型切换
```yaml
file:
  path: file/
  prefix: pre
  domain: domain/
  storage:
    type: minio   # minio / rustfs / seaweedfs / local

只需修改 storage.type,即可切换存储实现。

2. minio 配置

minio:
  url: http://localhost:9000
  accesskey: minioadmin
  secretkey: minioadmin123
  bucketname: xxx

3. rustfs 配置(s3 协议)

rustfs:
  url: http://localhost:9000
  accesskey: rustfsadmin
  secretkey: rustfsadmin
  bucketname: xxx

rustfs 兼容 s3 协议,可直接复用 minio sdk。

4. seaweedfs 配置

seaweedfs:
  url: http://127.0.0.1:8333
  accesskey: weed
  secretkey: weed
  bucketname: xxx

三、分片上传核心流程

1. 前端切片思路

前端将大文件切割为多个分片(如 5mb):

file
├── chunk_0
├── chunk_1
├── chunk_2
└── chunk_n

每个分片上传时携带:

  • 文件唯一标识(guid / md5)
  • 分片索引(chunkindex)
  • 总分片数(totalchunk)

2. 分片上传接口

post /file/chunk/upload

四、断点续传实现

1. 查询已上传分片

get /file/chunk/uploaded?guid=xxx

返回示例:

[0,1,3,5]

前端只上传缺失分片即可。

2. 实现原则

  • 是否已上传以「存储层」为准
  • 不依赖内存或 redis
  • 服务重启不影响续传

五、上传进度计算

进度 = 已上传分片数 / 总分片数 × 100%

示例返回:

{
  "uploaded": 6,
  "total": 10,
  "percent": 60
}

六、存储层抽象设计

1. 统一接口定义

public interface storageservice {
    void uploadchunk(string path, inputstream inputstream);
    boolean exists(string path);
    list<integer> listchunks(string prefix);
    void mergechunks(string chunkprefix, string targetpath, int totalchunk);
    void deletechunks(string chunkprefix);
}

2. minio / rustfs 实现(s3 通用)

@slf4j
public class miniostorageservice implements storageservice {
    private final minioclient minioclient;
    private final string bucket;
    public miniostorageservice(minioclient client, string bucket) {
        this.minioclient = client;
        this.bucket = bucket;
    }
    @override
    public void uploadchunk(string path, inputstream inputstream) {
        try {
            minioclient.putobject(
                putobjectargs.builder()
                    .bucket(bucket)
                    .object(path)
                    .stream(inputstream, -1, 5 * 1024 * 1024)
                    .build()
            );
        } catch (exception e) {
            throw new runtimeexception("分片上传失败", e);
        }
    }
    @override
    public boolean exists(string path) {
        try {
            minioclient.statobject(
                statobjectargs.builder()
                    .bucket(bucket)
                    .object(path)
                    .build()
            );
            return true;
        } catch (exception e) {
            return false;
        }
    }
    @override
    public list<integer> listchunks(string prefix) {
        list<integer> chunks = new arraylist<>();
        iterable<result<item>> results =
            minioclient.listobjects(
                listobjectsargs.builder()
                    .bucket(bucket)
                    .prefix(prefix)
                    .build()
            );
        for (result<item> r : results) {
            string name = r.get().objectname();
            chunks.add(integer.parseint(
                name.substring(name.lastindexof("_") + 1)));
        }
        return chunks;
    }
    @override
    public void mergechunks(string chunkprefix,
                            string targetpath,
                            int totalchunk) {
        try {
            bytearrayoutputstream out = new bytearrayoutputstream();
            for (int i = 0; i < totalchunk; i++) {
                inputstream in = minioclient.getobject(
                    getobjectargs.builder()
                        .bucket(bucket)
                        .object(chunkprefix + "/chunk_" + i)
                        .build()
                );
                ioutils.copy(in, out);
            }
            uploadchunk(
                targetpath,
                new bytearrayinputstream(out.tobytearray()));
        } catch (exception e) {
            throw new runtimeexception("分片合并失败", e);
        }
    }
    @override
    public void deletechunks(string chunkprefix) {
        // 可按需实现批量删除
    }
}

七、业务 service 实现

@service
public class fileuploadserviceimpl implements fileuploadservice {
    @autowired
    private storageservice storageservice;
    @override
    public void uploadchunk(chunkuploaddto dto) throws ioexception {
        string path = dto.getguid() + "/chunk_" + dto.getchunkindex();
        if (storageservice.exists(path)) {
            return;
        }
        storageservice.uploadchunk(
            path, dto.getfile().getinputstream());
    }
    @override
    public list<integer> uploadedchunks(string guid) {
        return storageservice.listchunks(guid + "/");
    }
    @override
    public void merge(string guid, int totalchunk) {
        storageservice.mergechunks(
            guid, guid + ".final", totalchunk);
        storageservice.deletechunks(guid + "/");
    }
}

八、controller 接口

@restcontroller
@requestmapping("/file/chunk")
public class fileuploadcontroller {
    @autowired
    private fileuploadservice fileuploadservice;
    @postmapping("/upload")
    public void upload(chunkuploaddto dto) throws ioexception {
        fileuploadservice.uploadchunk(dto);
    }
    @getmapping("/uploaded")
    public list<integer> uploaded(@requestparam string guid) {
        return fileuploadservice.uploadedchunks(guid);
    }
    @postmapping("/merge")
    public void merge(@requestparam string guid,
                      @requestparam integer totalchunk) {
        fileuploadservice.merge(guid, totalchunk);
    }
}

九、总结

本文实现了一套 spring boot 大文件上传方案,具备:

  • 分片上传
  • 断点续传
  • 上传进度计算
  • 多存储后端解耦
  • yml 配置快速切换

适用于文件中心、数据平台、企业网盘等场景,可直接用于生产环境

到此这篇关于spring boot 实现分片上传、断点续传与进度条的文章就介绍到这了,更多相关springboot分片上传断点续传内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com