1.创建SpringBoot项目
本项目采用springboot + mybatis-plus +jquery +thymeleaf组成
2.项目流程图
3.在pom中添加以下依赖
org.projectlombok lomboktrue commons-io commons-io2.4 commons-fileupload commons-fileupload1.3.1 mysql mysql-connector-javaruntime com.baomidou mybatis-plus-boot-starter3.3.2
4.在application.properties配置文件中
spring.resources.static-locations=classpath:/static server.port=8000 #设置上传图片的路径 file.basepath=D:/BaiduNetdiskDownload/ # 设置单个文件大小 spring.servlet.multipart.max-file-size= 50MB # 设置单次请求文件的总大小 spring.servlet.multipart.max-request-size= 50MB ##设置要连接的mysql数据库 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai spring.datasource.username=root spring.datasource.password=root
5.在数据库创建表
create table file ( id INTEGER primary key AUTO_INCREMENT comment 'id', path varchar(100) not null COMMENT '相对路径', name varchar(100) COMMENT '文件名', suffix varchar(10) COMMENT '文件后缀', size int COMMENT '文件大小|字节B', created_at BIGINT(20) COMMENT '文件创建时间', updated_at bigint(20) COMMENT '文件修改时间', shard_index int comment '已上传分片', shard_size int COMMENT '分片大小|B', shard_total int COMMENT '分片总数', file_key varchar(100) COMMENT '文件标识' )
6.创建实体类
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName(value = "file")
public class FileDTO {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String path;
private String name;
private String suffix;
private Integer size;
private Long createdAt;
private Long updatedAt;
private Integer shardIndex;
private Integer shardSize;
private Integer shardTotal;
private String fileKey;
}
7.创建mapper
import com.baomidou.mybatisplus.core.mapper.baseMapper; import com.example.demo.upload.entity.FileDTO; import org.springframework.stereotype.Repository; @Repository public interface FileMapper extends baseMapper{ }
8.创建service
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo.upload.dao.FileMapper;
import com.example.demo.upload.entity.FileDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class FileService {
@Autowired
private FileMapper fileMapper;
//保存文件
public void save(FileDTO file1){
//根据 数据库的 文件标识来查询 当前视频 是否存在
LambdaQueryWrapper lambda = new QueryWrapper().lambda();
lambda.eq(FileDTO::getFileKey,file1.getFileKey());
List fileDTOS = fileMapper.selectList(lambda);
//如果存在就话就修改
if(fileDTOS.size()!=0){
//根据key来修改
LambdaQueryWrapper lambda1 = new QueryWrapper().lambda();
lambda1.eq(FileDTO::getFileKey,file1.getFileKey());
fileMapper.update(file1,lambda1);
}else
{
//不存在就添加
fileMapper.insert(file1);
}
}
//检查文件
public List check(String key){
LambdaQueryWrapper lambda = new QueryWrapper().lambda();
lambda.eq(FileDTO::getFileKey,key);
List dtos = fileMapper.selectList(lambda);
return dtos;
}
}
9.创建utils
import lombok.Data;
@Data
public class Result {
// 成功状态码
public static final int SUCCESS_CODE = 200;
// 请求失败状态码
public static final int FAIL_CODE = 500;
// 查无资源状态码
public static final int NOTF_FOUNT_CODE = 404;
// 无权访问状态码
public static final int ACCESS_DINE_CODE = 403;
private int code;
private String msg;
private Object data;
public static Result ok() {
Result r = new Result();
r.setCode(SUCCESS_CODE);
r.setMsg("请求成功!");
r.setData(null);
return r;
}
public static Result fail() {
Result r = new Result();
r.setCode(FAIL_CODE);
r.setMsg("请求失败!");
r.setData(null);
return r;
}
public static Result ok(String msg) {
Result r = new Result();
r.setCode(SUCCESS_CODE);
r.setMsg(msg);
r.setData(null);
return r;
}
public static Result fail(String msg) {
Result r = new Result();
r.setCode(FAIL_CODE);
r.setMsg(msg);
r.setData(null);
return r;
}
public static Result ok(String msg, Object data) {
Result r = new Result();
r.setCode(SUCCESS_CODE);
r.setMsg(msg);
r.setData(data);
return r;
}
public static Result fail(String msg, Object data) {
Result r = new Result();
r.setCode(FAIL_CODE);
r.setMsg(msg);
r.setData(data);
return r;
}
public Result code(Integer code){
this.setCode(code);
return this;
}
public Result data(Object data){
this.setData(data);
return this;
}
public Result msg(String msg){
this.setMsg(msg);
return this;
}
}
10.创建controller
import com.example.demo.upload.entity.FileDTO;
import com.example.demo.upload.service.FileService;
import com.example.demo.upload.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.List;
import java.util.UUID;
@Controller
@RequestMapping("/file")
@Slf4j
public class FileController {
@Autowired
FileService fileService;
public static final String BUSINESS_NAME = "普通分片上传";
// 设置图片上传路径
@Value("${file.basepath}")
private String basePath;
@RequestMapping("/show")
public String show(){
return "file";
}
@RequestMapping("/upload")
@ResponseBody
public String upload(MultipartFile file,
String suffix,
Integer shardIndex,
Integer shardSize,
Integer shardTotal,
Integer size,
String key
) throws IOException, InterruptedException {
log.info("上传文件开始");
//文件的名称
String name = UUID.randomUUID().toString().replaceAll("-", "");
// 获取文件的扩展名
String ext = FilenameUtils.getExtension(file.getOriginalFilename());
//设置图片新的名字
String fileName = new StringBuffer().append(key).append(".").append(suffix).toString(); // course6sfSqfOwzmik4A4icMYuUe.mp4
//这个是分片的名字
String localfileName = new StringBuffer(fileName)
.append(".")
.append(shardIndex)
.toString(); // course6sfSqfOwzmik4A4icMYuUe.mp4.1
// 以绝对路径保存重名命后的图片
File targeFile=new File(basePath,localfileName);
//上传这个图片
file.transferTo(targeFile);
//数据库持久化这个数据
FileDTO file1=new FileDTO();
file1.setPath(basePath+localfileName);
file1.setName(name);
file1.setSuffix(ext);
file1.setSize(size);
file1.setCreatedAt(System.currentTimeMillis());
file1.setUpdatedAt(System.currentTimeMillis());
file1.setShardIndex(shardIndex);
file1.setShardSize(shardSize);
file1.setShardTotal(shardTotal);
file1.setFileKey(key);
//插入到数据库中
//保存的时候 去处理一下 这个逻辑
fileService.save(file1);
//判断当前是不是最后一个分页 如果不是就继续等待其他分页 合并分页
if(shardIndex .equals(shardTotal) ){
file1.setPath(basePath+fileName);
this.merge(file1);
}
return "上传成功";
}
@RequestMapping("/check")
@ResponseBody
public Result check(String key){
List check = fileService.check(key);
//如果这个key存在的话 那么就获取上一个分片去继续上传
if(check.size()!=0){
return Result.ok("查询成功",check.get(0));
}
return Result.fail("查询失败,可以添加");
}
private void merge(FileDTO fileDTO) throws FileNotFoundException, InterruptedException {
//合并分片开始
log.info("分片合并开始");
String path = fileDTO.getPath(); //获取到的路径 没有.1 .2 这样的东西
//截取视频所在的路径
path = path.replace(basePath,"");
Integer shardTotal= fileDTO.getShardTotal();
File newFile = new File(basePath + path);
FileOutputStream outputStream = new FileOutputStream(newFile,true); // 文件追加写入
FileInputStream fileInputStream = null; //分片文件
byte[] byt = new byte[10 * 1024 * 1024];
int len;
try {
for (int i = 0; i < shardTotal; i++) {
// 读取第i个分片
fileInputStream = new FileInputStream(new File(basePath + path + "." + (i + 1))); // course6sfSqfOwzmik4A4icMYuUe.mp4.1
while ((len = fileInputStream.read(byt)) != -1) {
outputStream.write(byt, 0, len);
}
}
} catch (IOException e) {
log.error("分片合并异常", e);
} finally {
try {
if (fileInputStream != null) {
fileInputStream.close();
}
outputStream.close();
log.info("IO流关闭");
} catch (Exception e) {
log.error("IO流关闭", e);
}
}
log.info("分片结束了");
//告诉java虚拟机去回收垃圾 至于什么时候回收 这个取决于 虚拟机的决定
System.gc();
//等待100毫秒 等待垃圾回收去 回收完垃圾
Thread.sleep(100);
log.info("删除分片开始");
for (int i = 0; i < shardTotal; i++) {
String filePath = basePath + path + "." + (i + 1);
File file = new File(filePath);
boolean result = file.delete();
log.info("删除{},{}", filePath, result ? "成功" : "失败");
}
log.info("删除分片结束");
}
}
11.创建html页面
Title
| 文件1 | |
12.测试
12.2:查看数据库
12.3 :已经上传成功 重新上传一次
12.4:当我上传一半的时候 (显示上传了一个文件 然后我们继续上传)
12.5:继续上传 查看目录 发现已经成功了
13.注意事项
13.1:程序中并没有去判断 你存在不存在 上传图片的地址 所以如果打算使用代码 请创建 上传图片的目录 D:/BaiduNetdiskDownload/
13.2 :使用代码前请修改配置文件中的 数据库连接
14.代码 直达地址
到此这篇关于SpringBoot 中大文件(分片上传)断点续传与极速秒传功能的实现的文章就介绍到这了,更多相关springboot大文件断点续传秒传内容请搜索考高分网以前的文章或继续浏览下面的相关文章希望大家以后多多支持考高分网!



