接着上一篇,实现多个大文件的断点续传。
前端JSP页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
文件上传
选择文件
后端Controller
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.alibaba.fastjson.JSON;
@Controller
@RequestMapping(value = "/uploadBig")
public class BigFileUploadController extends BaseController {
/** 日志记录 */
private static Logger logger = Logger.getLogger(BigFileUploadController.class);
/**
* 保存文件分片
* @param request HttpServletRequest
* @param response HttpServletResponse
*/
@RequestMapping(value = "/upload",
method = RequestMethod.POST)
public void upload(HttpServletRequest request, HttpServletResponse response) {
// 参数获取
String fileName = request.getParameter("name");
String fileMd5 = request.getParameter("fileMd5");
String chunk = request.getParameter("chunk");
SysUser user = getSysUser(request);
// 临时目录
String tempPath = FilePathUtil.getRootTempPath();
// 转换请求对象得到文件对象
MultipartHttpServletRequest Murequest = (MultipartHttpServletRequest) request;
Map files = Murequest.getFileMap();
if (null != files && !files.isEmpty()) {
for (MultipartFile item : files.values()) {
String tempDir = getTempDir(tempPath, user.getUserName(), fileName, fileMd5);
// 创建临时文件夹
File dir = new File(tempDir);
if (!dir.exists()) {
dir.mkdirs();
}
// 创建分片文件并保存
File chunkFile = new File(tempDir + File.separator + chunk);
try {
chunkFile.createNewFile();
item.transferTo(chunkFile);
} catch (IllegalStateException e) {
logger.error("保存分片文件出错:" + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
logger.error("保存分片文件出错:" + e.getMessage());
e.printStackTrace();
}
}
}
}
/**
* 校验分片是否已上传
*
* @Title: checkChunk
* @param request HttpServletRequest
* @param response HttpServletResponse
*/
@RequestMapping(value = "/check",
method = RequestMethod.POST)
public void checkChunk(HttpServletRequest request, HttpServletResponse response) {
// 获取参数
String fileName = request.getParameter("fileName");
String fileMd5 = request.getParameter("fileMd5");
String chunk = request.getParameter("chunk");
String chunkSize = request.getParameter("chunkSize");
SysUser user = getSysUser(request);
// 临时文件
String tempPath = FilePathUtil.getRootTempPath();
String tempDir = getTempDir(tempPath, user.getUserName(), fileName, fileMd5);
File chunkFile = new File(tempDir + File.separator + chunk);
int result = 0;
// 分片文件是否存在,尺寸是否一致
if (chunkFile.exists() && chunkFile.length() == Integer.parseInt(chunkSize)) {
result = 1;
}
returnJSONData(response, JSON.toJSONString(result));
}
/**
* 合并分片成完整文件
*
* @Title: mergeChunks
* @param request HttpServletRequest
* @param response HttpServletResponse
*/
@SuppressWarnings("resource")
@RequestMapping(value = "/merge",
method = RequestMethod.POST)
public void mergeChunks(HttpServletRequest request, HttpServletResponse response) {
// 获取参数
String fileName = request.getParameter("fileName");
String fileMd5 = request.getParameter("fileMd5");
SysUser user = getSysUser(request);
// 获得目标文件夹
String savePath = FilePathUtil.getFilePath();
// 创建目标文件夹
File saveDir = new File(savePath);
if (!saveDir.exists()) {
saveDir.mkdirs();
}
// 文件临时文件夹"根目录/temp/userName/文件名/MD5"
String tempDirPath = getTempDir(FilePathUtil.getRootTempPath(), user.getUserName(), fileName, fileMd5);
File tempDir = new File(tempDirPath);
// 获得分片文件列表
File[] fileArray = tempDir.listFiles(new FileFilter() {
// 只需要文件
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
return false;
} else {
return true;
}
}
});
// 转成集合进行排序后合并文件
List fileList = new ArrayList(Arrays.asList(fileArray));
Collections.sort(fileList, new Comparator() {
// 按文件名升序排列
@Override
public int compare(File o1, File o2) {
if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) {
return -1;
} else {
return 1;
}
}
});
// 目标文件
File outfile = new File(savePath + File.separator + fileName);
try {
outfile.createNewFile();
} catch (IOException e) {
logger.error("创建目标文件出错:" + e.getMessage());
e.printStackTrace();
}
// 执行合并操作
FileChannel outChannel = null;
FileChannel inChannel;
try {
outChannel = new FileOutputStream(outfile).getChannel();
for (File file : fileList) {
inChannel = new FileInputStream(file).getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inChannel.close();
file.delete();
}
outChannel.close();
} catch (FileNotFoundException e) {
logger.error("合并分片文件出错:" + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
logger.error("合并分片文件出错:" + e.getMessage());
e.printStackTrace();
}
// 删除临时文件夹 根目录/temp/userName/fileName
File tempFileDir = new File(
FilePathUtil.getRootTempPath() + File.separator + user.getUserName() + File.separator + fileName);
FileUtil.deleteDir(tempFileDir);
}
/**
* 获得分片文件临时保存路径
*
* @Title: getTempDir
* @param tempPath 临时文件根目录
* @param userName 用户名
* @param fileName 文件名
* @param fileMd5 文件MD5
* @return String 分片临时保存路径
*/
private String getTempDir(String tempPath, String userName, String fileName, String fileMd5) {
StringBuilder dir = new StringBuilder(tempPath);
dir.append(File.separator).append(userName);
dir.append(File.separator).append(fileName);
dir.append(File.separator).append(fileMd5);
return dir.toString();
}
}