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 ...
随机推荐
- Java集合框架源码(一)——hashMap
注:本人的源码基于JDK1.8.0,JDK的版本可以在命令行模式下通过java -version命令查看. 一首先我们来看一下HashMap类的定义: public class HashMap< ...
- [Windows Server 2008] MySQL单数据库迁移方法
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:MySQL ...
- 动软生成器添加Mysql注释
1.解决没有mysql注释问题 替换原文件下载地址 2.更新Models模板 <#@ template language="c#" HostSpecific="Tr ...
- Application crashes -程序崩溃原因
Typical errors that result in application crashes include: attempting to read or write memory that i ...
- C++算法库学习__std::sort__对 vector进行排序_排序后就可以进行使用std::lower_bound进行二分查找(查找第一个大于等于指定值的迭代器的位置)__std::unique
std::sort 对vector成员进行排序; std::sort(v.begin(),v.end(),compare); std::lower_bound 在排序的vector中进行 ...
- Java基础(五)--内部类
内部类简单来说就是把一个类的定义放到另一个类的定义内部 内部类分为:成员内部类.局部内部类.匿名内部类.静态内部类 成员内部类:最常见的内部类 public class Outter { privat ...
- 百度地图API获取数据
目前,大厂的服务范围越来越广,提供的数据信息也是比较全的,在生活服务,办公领域,人工智能等方面都全面覆盖,相对来说,他们的用户基数大,通过用户获取的信息也是巨大的.除了百度提供api,国内提供免费AP ...
- CMU-准备
TOEFL成绩90分以上,GPA大于3.0,GRE1250分以上(不做明确要求) 申请条件:GRE成绩,建议有专科成绩;托福250,雅思7.0;简历;3封推荐信 TOEFL(The Test of E ...
- 【Js 文件】 相关
防止浏览器缓存 <script src="/js/common.js?t=<%=DateTime.Now.ToFileTime().ToString()%>>&quo ...
- __cdecl、__stdcall、__fastcall 与 __pascal 浅析
call 指令与 retn 指令 首先我们得了解 CALL 和 RETN 指令的作用,才能更好地理解调用规则,这也是先决条件. 实际上,CALL 指令就是先将下一条指令的 EIP 压栈,然后 JMP ...