主要思路就是将大文件分成多个小文件上传,服务器端将上传上来的小文件先保存成各个临时文件,当所有分片的文件上传完毕后,调用接口将所有的临时文件合并成一个文件
我这里只是一个小小的demo,如果想做好,首先是前端根据文件获取到一个md5值,然后在上传文件的时候根据这个md5值检测之前是否有上传文件,如果没有则从开始位置上传(上传成功后要把相应的数据保存到数据库表里面),如果之前有上传则查看上传到了什么位置,然会给前端,前端好接着从之前的位置传数据
后台代码
package cn.com.modules.file;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
import java.io.Serializable;
/**
* @Author: luojie
* @Date: 2021/2/20 11:09
*/
@Data
public class Chunk implements Serializable {
private Long id;
/**
* 当前文件块,从1开始
*/
private Integer chunkNumber;
/**
* 分块大小
*/
private Long chunkSize;
/**
* 当前分块大小
*/
private Long currentChunkSize;
/**
* 总大小
*/
private Long totalSize;
/**
* 文件标识
*/
private String identifier;
/**
* 文件名
*/
private String filename;
/**
* 相对路径
*/
private String relativePath;
/**
* 总块数
*/
private Integer totalChunks;
/**
* 文件类型
*/
private String type;
private MultipartFile file;
}
package cn.com.esrichina.sip.modules.file;
import cn.com.esrichina.sip.commons.exception.RaccoonException;
import io.swagger.annotations.Api;
import org.apache.commons.io.FileUtils;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @Author: luojie
* @Date: 2021/2/20 11:10
*/
@RestController
@Api(value = "/upload", description = "文件上传,支持文件分片上传")
@RequestMapping("/upload")
@CrossOrigin
public class UploadController {
private static final String filePath = "C:/resources/sip";
private static final String filePathTemp = "C:/resources/sip/temp";
/**
* 分片上传
*/
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public Boolean upload(HttpServletRequest request, Chunk chunk) throws IOException {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
MultipartFile file = chunk.getFile();
if (file == null) {
throw new RaccoonException(400, "参数验证失败!");
}
Integer chunkNumber = chunk.getChunkNumber();
if (chunkNumber == null) {
chunkNumber = 0;
}
java.io.File outFile = new java.io.File(filePathTemp + java.io.File.separator + chunk.getIdentifier(), chunkNumber + ".part");
InputStream inputStream = file.getInputStream();
FileUtils.copyInputStreamToFile(inputStream, outFile);
}
return true;
}
/**
* 合并所有分片
* guid 就是 identifier(文件标识)
*/
@GetMapping("/merge")
@ResponseBody
public Boolean mergeFile(String filename, String guid) throws Exception {
java.io.File file = new java.io.File(filePathTemp + java.io.File.separator + guid);
if (file.isDirectory()) {
java.io.File[] files = file.listFiles();
if (files != null && files.length > 0) {
java.io.File partFile = new java.io.File(filePath + java.io.File.separator + filename);
for (int i = 1; i <= files.length; i++) {
java.io.File s = new java.io.File(filePathTemp + java.io.File.separator + guid, i + ".part");
FileOutputStream destTempfos = new FileOutputStream(partFile, true);
FileUtils.copyFile(s, destTempfos);
destTempfos.close();
}
FileUtils.deleteDirectory(file);
}
}
return true;
}
}
前端测试代码
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>Document</title>
</head>
<body>
<form id="f" method="post" action="#" enctype="multipart/form-data">
选择图片:<input type="file" id="file6" name="file1"><br />
</form>
<a href="#" class="btnFile6">提交</a>
<script src="jquery-3.0.0.js"></script>
<script>
$(function(){
$(".btnFile6").click(function () {
var upload = function (file, skip) {
var formData = new FormData();//初始化一个FormData对象
var blockSize = 1024*1024;//每块的大小
var nextSize = Math.min((skip + 1) * blockSize, file.size);//读取到结束位置
var fileData = file.slice(skip * blockSize, nextSize);//截取 部分文件 块
formData.append("file", fileData);//将 部分文件 塞入FormData
formData.append("fileName", file.name);//保存文件名字
formData.append("chunkSize", blockSize);
formData.append("totalSize", file.size);
formData.append("identifier", "AA");
formData.append("chunkNumber", (skip + 1));
$.ajax({
url: "http://127.0.0.1:10089/upload",
type: "POST",
data: formData,
processData: false, // 告诉jQuery不要去处理发送的数据
contentType: false, // 告诉jQuery不要去设置Content-Type请求头
success: function (responseText) {
$(".result").html("已经上传了" + (skip + 1) + "块文件");
if (file.size <= nextSize) {//如果上传完成,则跳出继续上传
//全部上传成功后执行下面的语句
console.log("--上传完成----");
//合并文档
$.ajax({
type: "GET",
url: "http://127.0.0.1:10089/upload/merge?filename=开发文档.docx&guid=AA",
dataType: "json",
success:function (message) {
},
error:function (message) {
alert('系统异常');
}
});
return;
}
upload(file, ++skip);//递归调用
}
});
};
var file = $("#file6")[0].files[0];
upload(file, 0);
});
})
</script>
</body>
</html>
浙公网安备 33010602011771号