java实现文件断点续传
//下载文件(断点续传测试)
@RequestMapping("/getFileOutputStream1")
public void getFileOutputStream1(HttpServletRequest request,HttpServletResponse response,String path,String contentType) {
response.setCharacterEncoding("utf-8");
//在获取文件流之前调用过validateFile接口,不需要再判断是否登录
//判断是否登录
if(!Utils.isLogin(request)) {
return;
}
//path = URLDecoder.decode(path); //解码
path = Utils.decodeStr(path);
path = EncrypAES.decrypt(path);
System.out.println("==========getFileOutputStream=========path:"+path+"\tcontentType:"+contentType);
File file = new File(path); //1、建立连接
if(file.isDirectory()) {
return;
}
ServletContext context = request.getServletContext();
// get MIME type of the file
String mimeType = context.getMimeType(path);
if (mimeType == null) {
// set to binary type if MIME mapping not found
mimeType = "application/octet-stream";
}
// set content attributes for the response
response.setContentType(mimeType);
// response.setContentLength((int) downloadFile.length());
// set headers for the response
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", file.getName());
response.setHeader(headerKey, headerValue);
// 解析断点续传相关信息
response.setHeader("Accept-Ranges", "bytes");
long downloadSize = file.length();
long fromPos = 0, toPos = 0;
if (request.getHeader("Range") == null) {
response.setHeader("Content-Length", downloadSize + "");
} else {
// 若客户端传来Range,说明之前下载了一部分,设置206状态(SC_PARTIAL_CONTENT)
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
String range = request.getHeader("Range");
String bytes = range.replaceAll("bytes=", "");
String[] ary = bytes.split("-");
fromPos = Long.parseLong(ary[0]);
if (ary.length == 2) {
toPos = Long.parseLong(ary[1]);
}
int size;
if (toPos > fromPos) {
size = (int) (toPos - fromPos);
} else {
size = (int) (downloadSize - fromPos);
}
response.setHeader("Content-Length", size + "");
downloadSize = size;
}
// Copy the stream to the response's output stream.
RandomAccessFile in = null;
OutputStream out = null;
try {
in = new RandomAccessFile(file, "rw");
// 设置下载起始位置
if (fromPos > 0) {
in.seek(fromPos);
}
// 缓冲区大小
int bufLen = (int) (downloadSize < 2048 ? downloadSize : 2048);
byte[] buffer = new byte[bufLen];
int num;
int count = 0; // 当前写到客户端的大小
out = response.getOutputStream();
while ((num = in.read(buffer)) != -1) {
out.write(buffer, 0, num);
count += num;
//处理最后一段,计算不满缓冲区的大小
if (downloadSize - count < bufLen) {
bufLen = (int) (downloadSize-count);
if(bufLen==0){
break;
}
buffer = new byte[bufLen];
}
}
response.flushBuffer();
} catch (IOException e) {
log.info("数据被暂停或中断。");
// e.printStackTrace();
} finally {
if (null != out) {
try {
out.close();
} catch (IOException e) {
log.info("数据被暂停或中断。");
// e.printStackTrace();
}
}
if (null != in) {
try {
in.close();
} catch (IOException e) {
log.info("数据被暂停或中断。");
//e.printStackTrace();
}
}
}
}