断点续传文件


import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.connector.ClientAbortException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Title: IndexController.java
 * @Package com.fhhr.controller
 * @Description:
 * @author ybwei
 * @date 2018年9月10日 下午12:11:04
 * @version V1.0
 */
@RestController
public class IndexController {
	private final Logger logger = LoggerFactory.getLogger(getClass());

	@Value("${file.download.path}")
	private String filePathName;

	/**
	 * 断点下载
	 * @param request
	 * @param response
	 * @param range
	 * @author ybwei
	 */
	@RequestMapping("/downloadFile")
	public void home(HttpServletRequest request, HttpServletResponse response,
			@RequestHeader(required = false) String range) {
		// 文件目录
		File file = new File(filePathName);

		// 开始下载位置
		long startByte = 0;
		// 结束下载位置
		long endByte = file.length() - 1;

		// 有range的话
		if (range != null && range.contains("bytes=") && range.contains("-")) {
			range = range.substring(range.lastIndexOf("=") + 1).trim();
			String ranges[] = range.split("-");
			try {
				// 判断range的类型
				if (ranges.length == 1) {
					// 类型一:bytes=-2343
					if (range.startsWith("-")) {
						endByte = Long.parseLong(ranges[0]);
					}
					// 类型二:bytes=2343-
					else if (range.endsWith("-")) {
						startByte = Long.parseLong(ranges[0]);
					}
				}
				// 类型三:bytes=22-2343
				else if (ranges.length == 2) {
					startByte = Long.parseLong(ranges[0]);
					endByte = Long.parseLong(ranges[1]);
				}

			} catch (NumberFormatException e) {
				startByte = 0;
				endByte = file.length() - 1;
			}
		}

		// 要下载的长度(为啥要加一问小学数学老师去)
		long contentLength = endByte - startByte + 1;
		// 文件名
		String fileName = file.getName();
		// 文件类型
		String contentType = request.getServletContext().getMimeType(fileName);

		// 解析断点续传相关信息
		response.setHeader("Accept-Ranges", "bytes");
		// 若客户端传来Range,说明之前下载了一部分,设置206状态(SC_PARTIAL_CONTENT)
		response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
		response.setContentType(contentType);
		response.setHeader("Content-Type", contentType);
		// 这里文件名换你想要的,inline表示浏览器直接实用(我方便测试用的)
		// 参考资料:http://hw1287789687.iteye.com/blog/2188500
		response.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
		response.setHeader("Content-Length", String.valueOf(contentLength));
		// [要下载的开始位置]-[结束位置]/[文件总大小]
		response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + file.length());

		BufferedOutputStream outputStream = null;
		RandomAccessFile randomAccessFile = null;
		// 已传送数据大小
		long transmitted = 0;
		try {
			randomAccessFile = new RandomAccessFile(file, "r");
			outputStream = new BufferedOutputStream(response.getOutputStream());
			byte[] buff = new byte[4096];
			int len = 0;
			randomAccessFile.seek(startByte);
			// contentLength)要放前面!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			// 不然会会先读取randomAccessFile,造成后面读取位置出错,找了一天才发现问题所在
			while ((transmitted + len) <= contentLength && (len = randomAccessFile.read(buff)) != -1) {
				outputStream.write(buff, 0, len);
				transmitted += len;
			}
			// 处理不足buff.length部分
			if (transmitted < contentLength) {
				len = randomAccessFile.read(buff, 0, (int) (contentLength - transmitted));
				outputStream.write(buff, 0, len);
				transmitted += len;
			}

			outputStream.flush();
			response.flushBuffer();
			randomAccessFile.close();
			logger.info("下载完毕:" + startByte + "-" + endByte + ":" + transmitted);

		} catch (ClientAbortException e) {
			logger.info("用户停止下载:" + startByte + "-" + endByte + ":" + transmitted);
			// 捕获此异常表示拥护停止下载
		} catch (IOException e) {
			logger.info("下载异常:", e);
		} finally {
			try {
				if (randomAccessFile != null) {
					randomAccessFile.close();
				}
			} catch (IOException e) {
				logger.info("下载异常:", e);
			}
		}

	}

}

猜你喜欢

转载自blog.csdn.net/xixingzhe2/article/details/82881798