Java 实现的断点下载
该断点下载可应用于浏览器或者迅雷等下载工具的下载,实现方式有多种多样的,本文仅仅研究了单线程的下载。迅雷等下载工具会自己主动将下载资源分块并记录每块的起始位置,然后依据系统性能。起多线程下载。
1. 基本原理
从Request Header的Range信息里面获取已经下载的文件大小,然后创建response的outputstream 向client(浏览器或者迅雷等下载工具)写,写的时候又利用header里面的“Content-Range”, 让client知道从哪个位置開始写;
读取网络资源方面,利用HttpClient模拟request请求,发起post或者get请求,仅仅是这个请求跟一般请求有点不一样:须要带上Range信息。告诉程序该从哪个位置開始读数据。
2. 须要使用的Java 组件
- HttpServletRequest / Response
- HttpClient
- ServletOutputStream
- BufferedInputStream
3. 代码实现
/**
* @desc 断点下载工具方法
* @param request
* @param response
* @param fileLength
* @param contentType
* @param fileName
* @param fileId
*/
public static void resumeDownload(HttpServletRequest request,
HttpServletResponse response, Long fileLength, String contentType,
String fileName, String fileId) {
ServletOutputStream out = null;
response.reset(); // 记录断点续传的開始点
long pos = 0;
if (null != request.getHeader("Range")) {
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
try {
pos = Long.parseLong(request.getHeader("Range")
.replaceAll("bytes=", "").replaceAll("-.*", ""));
} catch (NumberFormatException e) {
LOGGER.error(e.getMessage(), e);
pos = 0;
}
String contentRange = new StringBuffer("bytes ").append(pos + "")
.append("-").append((fileLength.intValue() - 1) + "")
.append("/").append(fileLength.intValue() + "").toString();
response.setHeader("Content-Range", contentRange);
} response.setHeader("Accept-Ranges", "bytes");
response.setHeader("Content-Length",
String.valueOf(fileLength.intValue() - pos));
response.setCharacterEncoding("UTF-8");
response.setContentType(contentType);
response.setHeader("Content-disposition", "attachment;filename=\""
+ fileName + "\"");
try {
out = response.getOutputStream();
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
} // 断点下载
CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(SysConf.getString("fezo.download.url")); List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair(SysConf.getString("fezo.download.param"), fileId)); HttpResponse httpResponse = null;
BufferedInputStream input = null;
try {
httpPost.setEntity(new UrlEncodedFormEntity(nvps)); httpPost.setHeader("Range", "bytes=" + pos + "-");
httpResponse = httpClient.execute(httpPost); input = new BufferedInputStream(httpResponse.getEntity().getContent()); byte[] buffer = new byte[CommonConstants.BUFFER_SIZE];
int len = -1;
while ((len = input.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.flush();
out.close();
input.close();
} catch (UnsupportedEncodingException e) {
LOGGER.error(e.getMessage(), e);
} catch (ClientProtocolException e) {
LOGGER.error(e.getMessage(), e);
} catch (IOException e) {
// 能够忽略这个异常。有可能是用户暂停下载,或者迅雷等下载工具分块下载
} finally {
try {
if (httpClient != null) httpClient.close();
} catch(IOException e) {
LOGGER.error(e.getMessage(), e);
}
}
}
>>>点击这里下载代码
4. 重点与难点
- 获取response的输出流程来向client提供下载功能,而不是简单的把数据写入到某个详细的文件,核心代码:out = response.getOutputStream();
- 头信息里面"Range" 和 "Conent-Range" 等信息的处理;
- 迅雷等多线程分块下载client下载的处理:还是要处理好"Range" 和 "Conent-Range" 等头部信息,迅雷会自己主动将文件内容分块、记录起始位置。
Java 实现的断点下载的更多相关文章
- Java实现多线程断点下载(下载过程中可以暂停)
线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配. ...
- Java之多线程断点下载的实现
RandomAccessFile类: 此类的实例支持对随机訪问文件的读取和写入.随机訪问文件的行为相似存储在文件系统中的一个大型 byte 数组. 存在指向该隐含数组.光标或索引,称为文件指针.输入操 ...
- 【Java EE 学习 22 下】【单线程下载】【单线程断点下载】【多线程下载】
一.文件下载简述 1.使用浏览器从网页上下载文件,Servlet需要增加一些响应头信息 (1)response.setContentType("application/force-downl ...
- Android(java)学习笔记216:多线程断点下载的原理(Android实现)
之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1.新建一个Android工程: (1)其中我们先实现布局 ...
- java多线程下载文件和断点下载
多线程,断点下载文件 import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; impor ...
- Android(java)学习笔记159:多线程断点下载的原理(Android实现)
之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1. 新建一个Android工程: (1)其中我们先实现布 ...
- java多线程断点下载原理(代码实例演示)
原文:http://www.open-open.com/lib/view/open1423214229232.html 其实多线程断点下载原理,很简单的,那么我们就来先了解下,如何实现多线程的断点下载 ...
- Java 断点下载(下载续传)服务端及客户端(Android)代码
原文: Java 断点下载(下载续传)服务端及客户端(Android)代码 - Stars-One的杂货小窝 最近在研究断点下载(下载续传)的功能,此功能需要服务端和客户端进行对接编写,本篇也是记录一 ...
- Java多线程断点下载文件
Java实现断点续传+多线程下载 如下代码所示,每一步都有注解 思路: 通过URL连接到服务器上要下载的文件,得到文件的大小: 算出每条线程下载的开始位置和结束位置,例如,有两条线程下载100Byte ...
随机推荐
- centos上安装supervisor来管理dotnetcore等应用程序
supervisor 介绍: 这是一款用python编写的进程管理工具,可以守护他管理的所有进程,防止异常退出,以及提供一个可视化的web界面来手动管理,打开关闭重启各种应用,界面如下: 关于在cen ...
- Linux系统命令及文件的浏览、管理和维护
在linux中什么是一个文件的路径呢,说白了就是这个文件存在的地方,例如在上一章提到的/root/.ssh/authorized_keys 这就是一个文件的路径.如果你告诉系统这个文件的路径,那么系统 ...
- Mysql导入导出大量数据的方法、备份恢复办法
经常使用PHP+Mysql的朋友一般都是通过phpmyadmin来管理数据库的.日常的一些调试开发工作,使用phpmyadmin确实很方便.但是当我们需要导出几百兆甚至几个G的数据库时,phpmyad ...
- HDU_1207_汉诺塔2
汉诺塔II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- HTML5 实现Link跳线效果
之前我们推出过Flex版本的Link跳线效果,现在基于HTML5新版本的跳线效果也实现了,细微之处我们进行了改进,如link倾斜的时候Offset方向始终保持垂直等.先看效果.实现的算法和Flex基本 ...
- 洛谷——P1413 坚果保龄球
P1413 坚果保龄球 题目描述 PVZ这款游戏中,有一种坚果保龄球.zombie从地图右侧不断出现,向左走,玩家需要从左侧滚动坚果来碾死他们. 我们可以认为地图是一个行数为6,列数为60的棋盘.zo ...
- 洛谷——P2846 [USACO08NOV]光开关Light Switching
P2846 [USACO08NOV]光开关Light Switching 题目大意: 灯是由高科技——外星人鼠标操控的.你只要左击两个灯所连的鼠标, 这两个灯,以及之间的灯都会由暗变亮,或由亮变暗.右 ...
- Linux下“任务管理器”
也不知道linux叫不叫任务管理器. Ctrl+Alt+T打开终端,输入top,就会出现一堆东西. 如果有个东西未响应了,就可以输入k+这个进程的pid就可以杀死它. https://blog.csd ...
- buf.readInt32BE()
buf.readInt32BE(offset[, noAssert]) buf.readInt32LE(offset[, noAssert]) offset {Number} 0 <= offs ...
- Import CAD geometry in BladeModeler, turbogrid
Table of Contents 1. Import CAD geometry in BladeModeler, turbogrid 1 Import CAD geometry in BladeMo ...