# SpringBoot File Uploader
# 简介
采用前后端分离的方式进行开发,实现了几种常用的文件上传功能。 前端采用 vue.js + plupload + element-ui 实现了文件在浏览器端的发送, 后端采用 spring boot + spring + spring mvc + mybatis 实现了文件在服务器端的接收和存储。
***本项目为后端实现***
# 效果图
### 单文件上传
![](https://i.imgur.com/vBr8ZJq.gif)
### 多文件上传
![](https://i.imgur.com/Db6eaMJ.gif)
### 大文件上传
![](https://i.imgur.com/qAyksE8.gif)
### 断点续传
![](https://i.imgur.com/I1G01MT.gif)
### 文件秒传
![](https://i.imgur.com/XHZHGeo.gif)
### 图片上传
![](https://i.imgur.com/HFZQnV3.gif)
# 后端实现
## 未分块上传
采用MultipartFile接收上传文件并使用FileOutputStream写入文件
```java
/**
* 写入文件
* @param target
* @param src
* @throws IOException
*/
public static void write(String target, InputStream src) throws IOException {
OutputStream os = new FileOutputStream(target);
byte[] buf = new byte[1024];
int len;
while (-1 != (len = src.read(buf))) {
os.write(buf,0,len);
}
os.flush();
os.close();
}
```
## 分块上传
采用MultipartFile接收上传文件的分块文件,上传参数包括:size:文件大小,chunk:分块号,chunks:总分块数
```java
@PostMapping("/")
public void upload(String name,
String md5,
Long size,
Integer chunks,
Integer chunk,
MultipartFile file) throws IOException {
if (chunks != null && chunks != 0) {
fileService.uploadWithBlock(name, md5,size,chunks,chunk,file);
} else {
fileService.upload(name, md5,file);
}
}
```
### 分块上传信息的存储
使用Map来存储分块的上传信息,key为文件唯一标识由前端发送这里采用文件MD5作为文件的唯一标识,value为自定义的静态内部类,其中name属性为文件在服务器端存储的随机文件名其在该文件的第一个分块上传到服务器时随机生成(UUID),boolean数组记录了分块的上传情况已上传置为true。
```java
/**
* 分块上传工具类
*/
public class UploadUtils {
/**
* 内部类记录分块上传文件信息
*/
private static class Value {
String name;
boolean[] status;
Value(int n) {
this.name = generateFileName();
this.status = new boolean[n];
}
}
private static Map<String, Value> chunkMap = new HashMap<>();
/**
* 判断文件所有分块是否已上传
* @param key
* @return
*/
public static boolean isUploaded(String key) {
if (isExist(key)) {
for (boolean b : chunkMap.get(key).status) {
if (!b) {
return false;
}
}
return true;
}
return false;
}
/**
* 判断文件是否有分块已上传
* @param key
* @return
*/
private static boolean isExist(String key) {
return chunkMap.containsKey(key);
}
/**
* 为文件添加上传分块记录
* @param key
* @param chunk
*/
public static void addChunk(String key, int chunk) {
chunkMap.get(key).status[chunk] = true;
}
/**
* 从map中删除键为key的键值对
* @param key
*/
public static void removeKey(String key) {
if (isExist(key)) {
chunkMap.remove(key);
}
}
/**
* 获取随机生成的文件名
* @param key
* @param chunks
* @return
*/
public static String getFileName(String key, int chunks) {
if (!isExist(key)) {
synchronized (UploadUtils.class) {
if (!isExist(key)) {
chunkMap.put(key, new Value(chunks));
}
}
}
return chunkMap.get(key).name;
}
}
```
### 分块写入文件
使用RandomAccessFile随机读写文件,通过targetSize指定文件的大小,通过seek定位分块在文件中对应位置,通过write方法进行写入。
```java
/**
* 分块写入文件
* @param target
* @param targetSize
* @param src
* @param srcSize
* @param chunks
* @param chunk
* @throws IOException
*/
public static void writeWithBlok(String target, Long targetSize, InputStream src, Long srcSize, Integer chunks, Integer chunk) throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile(target,"rw");
randomAccessFile.setLength(targetSize);
if (chunk == chunks - 1 && chunk != 0) {
randomAccessFile.seek(chunk * (targetSize - srcSize) / chunk);
} else {
randomAccessFile.seek(chunk * srcSize);
}
byte[] buf = new byte[1024];
int len;
while (-1 != (len = src.read(buf))) {
randomAccessFile.write(buf,0,len);
}
randomAccessFile.close();
}
```
### 分块上传逻辑
每次分块上传时首先获取对应文件在服务器端生成的随机文件名,如果不存在即在这之前还没有分块上传,则创建文件分块存储信息的键值对并存入map中,同时返回刚生成的随机文件名。然后将分块写入文件,同时将boolean数组中当前对应分块的位置置为true。最后判断该文件的所有分块是否全部上传,如果已全部上传完成则将文件信息写入数据库同时删除map中对应的键值对。
> ps: 曾用文件夹存储上传分块,当分块全部上传完成时按顺序合并文件夹内所有分块,然后删除文件夹,后来发现RandomAccessFile果断弃坑。
```java
/**
* 分块上传文件
* @param md5
* @param size
* @param chunks
* @param chunk
* @param file
* @throws IOException
*/
public void uploadWithBlock(String name,
String md5,
Long size,
Integer chunks,
Integer chunk,
MultipartFile file) throws IOException {
String fileName = getFileName(md5, chunks);
FileUtils.writeWithBlok(UploadConfig.path + fileName, size, file.getInputStream(), file.getSize(), chunks, chunk);
addChunk(md5,chunk);
if (isUploaded(md5)) {
removeKey(md5);
fileDao.save(new File(name, md5,UploadConfig.path + fileName, new Date()));
}
}
```
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
基于SpringBoot的文件上传系统,前后端分离,单文件上传,多文件上传,大文件上传,断点续传,文件秒传,图片上传 项目经过严格测试,确保可以运行! 采用前后端分离的方式进行开发,实现了几种常用的文件上传功能。 前端采用 vue.js + plupload + element-ui 实现了文件在浏览器端的发送, 后端采用 spring boot + spring + spring mvc + mybatis 实现了文件在服务器端的接收和存储。 采用前后端分离的方式进行开发,实现了几种常用的文件上传功能。 前端采用 vue.js + plupload + element-ui 实现了文件在浏览器端的发送, 后端采用 spring boot + spring + spring mvc + mybatis 实现了文件在服务器端的接收和存储。 采用前后端分离的方式进行开发,实现了几种常用的文件上传功能。 前端采用 vue.js + plupload + element-ui 实现了文件在浏览器端的发送, 后端采用 spring boot + spring + spring mvc
资源推荐
资源详情
资源评论
收起资源包目录
springboot-file-uploader-master.zip (25个子文件)
springboot-file-uploader-master
mvnw.cmd 5KB
pom.xml 3KB
src
test
java
cn
attackme
myuploader
dao
FileDaoTests.java 4KB
MyUploaderApplicationTests.java 352B
main
resources
mapper
FileMapper.xml 3KB
logback.xml 4KB
schema.sql 453B
application.yml 455B
java
cn
attackme
myuploader
controller
TestExceptionController.java 1KB
FileUploadController.java 1KB
BigFileUploadController.java 2KB
QuickUploadController.java 897B
utils
LogUtils.java 2KB
UploadUtils.java 2KB
FileUtils.java 2KB
dao
FileDao.java 695B
service
FileService.java 2KB
model
File.java 991B
MyUploaderApplication.java 334B
config
UploadConfig.java 347B
SwaggerConfig.java 2KB
LogAspect.java 645B
mvnw 6KB
.gitignore 257B
README.md 6KB
共 25 条
- 1
资源评论
- 心之语歌2024-04-24资源很实用,内容详细,值得借鉴的内容很多,感谢分享。
白话机器学习
- 粉丝: 8173
- 资源: 7687
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- IMG_5905.PNG
- Cyclone Version 9.51
- 高性能量化回测工具 hikyuu 2.0.3 python 3.12 windows 安装包
- 省级城乡居民基本养老保险情况数据集(2010-2022年).xlsx
- 舞队填写版.cpp
- 基于BP神经网络的多输入单输出回归预测.zip
- 高性能量化回测工具 hikyuu 2.0.3 python 3.9 windows 安装包
- 省级城镇职工基本养老保险情况2000-2022年.xlsx
- 高性能量化回测工具 hikyuu 2.0.3 python 3.10 windows 安装包
- 算法部署-使用OpenVINO+C#部署PaddleOCR字符识别算法-项目源码-优质项目实战.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功