1.包括核对是否已有文件,拆分文件,合并文件
2.使用流解决
package com.cty.demo;
import com.cty.domain.MultipartFileParam;
import com.cty.util.JsonResult;
import org.apache.commons.io.FileUtils;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.*;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/bigFile")
public class BigFileTest {
private Logger logger = LoggerFactory.getLogger(BigFileTest.class);
private String fileStorePath = "/Users/chentingyi/cty/java/project/demo/test/temp";
/**
* @param fileMd5
* @Title: 判断文件是否上传过,是否存在分片,断点续传
* @MethodName: checkBigFile
* @Exception
* @Description: 文件已存在,1
* 文件没有上传过,0
* 文件上传中断过,2 以及现在有的数组分片索引
*/
@RequestMapping(value = "/check", method = RequestMethod.POST)
@ResponseBody
public JsonResult checkBigFile(String fileMd5) {
JsonResult jr = new JsonResult();
// 秒传
File mergeMd5Dir = new File(fileStorePath + "/" + "merge" + "/" + fileMd5);
if (mergeMd5Dir.exists()) {
mergeMd5Dir.mkdirs();
jr.setResultCode(1);//文件已存在
return jr;
}
// 读取目录里的所有文件
File dir = new File(fileStorePath + "/" + fileMd5);
File[] childs = dir.listFiles();
if (childs == null) {
jr.setResultCode(0);//文件没有上传过
} else {
jr.setResultCode(2);//文件上传中断过,除了状态码为2,还有已上传的文件分片索引
List<String> list = Arrays.stream(childs).map(f->f.getName()).collect(Collectors.toList());
jr.setResultData(list.toArray());
}
return jr;
}
/**
* 上传文件
* @param param
* @param request
* @return
* @throws Exception
*/
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public JsonResult filewebUpload(MultipartFileParam param, HttpServletRequest request) {
JsonResult jr = new JsonResult();
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
// 文件名
String fileName = param.getName();
// 文件每次分片的下标
int chunkIndex = param.getChunk();
if (isMultipart) {
File file = new File(fileStorePath + "/" + param.getMd5());
if (!file.exists()) { // 没有文件创建文件
file.mkdir();
}
File chunkFile = new File(
fileStorePath + "/" + param.getMd5() + "/" + chunkIndex);
try {
FileUtils.copyInputStreamToFile(param.getFile().getInputStream(), chunkFile); // 流文件操作
} catch (Exception e) {
jr.setResultCode(-1);
e.printStackTrace();
}
}
logger.info("文件-:{}的小标-:{},上传成功", fileName, chunkIndex);
File dir = new File(fileStorePath + "/" + param.getMd5());
File[] childs = dir.listFiles();
if(childs!=null){
jr.setResultData(childs.length); // 返回上传了几个,即为上传进度
}
return jr;
}
/**
* 分片上传成功之后,合并文件
* @param request
* @return
*/
@RequestMapping(value = "/merge", method = RequestMethod.POST)
@ResponseBody
public JsonResult filewebMerge(HttpServletRequest request) {
FileChannel outChannel = null;
JsonResult jr = new JsonResult();
int code =0;
try {
String fileName = request.getParameter("fileName");
String fileMd5 = request.getParameter("fileMd5");
// 读取目录里的所有文件
File dir = new File(fileStorePath + "/" + fileMd5);
File[] childs = dir.listFiles();
if (Objects.isNull(childs) || childs.length == 0) {
jr.setResultCode(-1);
return jr;
}
// 转成集合,便于排序
List<File> fileList = new ArrayList<File>(Arrays.asList(childs));
Collections.sort(fileList, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) {
return -1;
}
return 1;
}
});
// 合并后的文件
File outputFile = new File(fileStorePath + "/" + "merge" + "/" + fileMd5 + "/" + fileName);
// 创建文件
if (!outputFile.exists()) {
File mergeMd5Dir = new File(fileStorePath + "/" + "merge" + "/" + fileMd5);
if (!mergeMd5Dir.exists()) {
mergeMd5Dir.mkdirs();
}
logger.info("创建文件");
outputFile.createNewFile();
}
outChannel = new FileOutputStream(outputFile).getChannel();
FileChannel inChannel = null;
try {
for (File file : fileList) {
inChannel = new FileInputStream(file).getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inChannel.close();
// 删除分片
file.delete();
}
} catch (Exception e) {
code =-1;
e.printStackTrace();
//发生异常,文件合并失败 ,删除创建的文件
outputFile.delete();
dir.delete();//删除文件夹
} finally {
if (inChannel != null) {
inChannel.close();
}
}
dir.delete(); //删除分片所在的文件夹
} catch (IOException e) {
code =-1;
e.printStackTrace();
} finally {
try {
if (outChannel != null) {
outChannel.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
jr.setResultCode(code);
return jr;
}
}
参考文章:http://blog.ncmem.com/wordpress/2023/09/18/java%e5%ae%9e%e7%8e%b0%e5%a4%a7%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e4%bb%a3%e7%a0%81%e8%af%a6%e8%a7%a3/
欢迎入群一起讨论