前言
因为公司需要开发一套文件管理系统,传统的上传如果是大文件的话会很慢,因此就使用了分片多线程上传来让其上传速度成倍提升。
后端
一、 验证片接口
/**
* 校验分片文件是否已经上传
* @param chunk 分片索引
* @param chunkSize 分片大小
* @param guid 文件唯一id
* @return 分片文件结果
*/
@PostMapping("checkMd5")
public AjaxResult checkMd5(@JsonString("chunk") Integer chunk, @JsonString("chunkSize") Integer chunkSize, @JsonString("guid") String guid) {
//临时文件路径
String tempPath = SweetNightConfig.getProfile() + File.separator + "temp";
//要验证的片文件
File checkFile = new File(tempPath + File.separator + guid + File.separator + chunk);
AjaxResult ajaxResult = new AjaxResult();
//比对片文件与其大小
if (checkFile.exists() && checkFile.length() == chunkSize) {
ajaxResult.put("ifExist", 1);
} else {
ajaxResult.put("ifExist", 0);
}
return ajaxResult;
二、片文件上传接口
/**
* 片文件上传
* @param file 片文件
* @param chunk 片索引
* @param guid 文件唯一id
*/
@PostMapping("upload")
public void upload(MultipartFile file, Integer chunk, String guid) {
//临时目录
String filePath = SweetNightConfig.getProfile() + File.separator + "temp" + File.separator + guid;
File tempFile = new File(filePath);
//如果目录不存在就创建临时目录
if (!tempFile.exists()) {
tempFile.mkdirs();
}
//如果未传片索引值就索引就为0
if (chunk == null) {
chunk = 0;
}
try {
//块文件
File dirFile = new File(filePath, String.valueOf(chunk));
//存储块文件到临时目录
file.transferTo(dirFile);
} catch (Exception e) {
e.printStackTrace();
}
}
三、片合并接口
/**
* 合并块
*
* @param guid 文件唯一id
* @param name 合并后的文件名
*/
@PostMapping("combineBlock")
public void combineBlock(@JsonString("guid") String guid, @JsonString("name") String name) {
//文件存储目录
String filePathStr = SweetNightConfig.getUploadPath();
//临时文件目录
File tempPath = new File(SweetNightConfig.getProfile() + File.separator + "temp" + File.separator + guid);
String realFilePath = FileUploadUtils.extractFilename(name);
//真实目录路径
filePathStr = filePathStr + "/" + StringUtils.substringBeforeLast(StringUtils.remove(realFilePath, Constants.RESOURCE_PREFIX), "/") + "/";
File filePath = new File(filePathStr);
//判断存储目录是否存在不存在先创建
if (!filePath.exists()) {
filePath.mkdirs();
}
//合并后的文件路径
File file = new File(filePathStr + File.separator + name);
FileOutputStream fileOutputStream = null;
FileChannel fileChannel = null;
FileChannel fcout = null;
try {
fileOutputStream = new FileOutputStream(file, true);
fcout = fileOutputStream.getChannel();
//判断临时文件是否存在
if (tempPath.exists()) {
//获取目录下的所有文件
File[] tempFiles = tempPath.listFiles();
//按文件名进行排序
Arrays.sort(tempFiles, (o1, o2) -> {
if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) {
return -1;
}
if (Integer.parseInt(o1.getName()) == Integer.parseInt(o2.getName())) {
return 0;
}
return 1;
});
// 分配缓冲区10M
ByteBuffer byteBuffer = ByteBuffer.allocate(10 * 1024 * 1024);
for (int i = 0; i < tempFiles.length; i++) {
FileInputStream fis = new FileInputStream(tempFiles[i]);
fileChannel = fis.getChannel();
if (fileChannel.read(byteBuffer) != -1) {
//缓冲区重设限制缓存区最大可写入数据为当前写入位置,且缓冲区从0开始计算
byteBuffer.flip();
//判断当前缓存区是否已经写完如果未写完继续写
while (byteBuffer.hasRemaining()) {
//将片数据写入文件中进行合并
fcout.write(byteBuffer);
}
}
//清除写完的缓冲区
byteBuffer.clear();
//关闭通道
fis.close();
//删除写完的块
tempFiles[i].delete();
}
//合并完成关闭文件流
fileOutputStream.close();
if (tempPath.isDirectory() && tempPath.exists()) {
System.gc();
//删除临时文件夹
tempPath.delete();
}
log.info(tempPath.getAbsolutePath());
}
} catch (Exception e) {
e.printStackTrace();
}
}
网友评论