java断点下载工具_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 nvps = new ArrayList();

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" 等头部信息,迅雷会自己主动将文件内容分块、记录起始位置。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值