欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

Java 实现的断点下载,Java实现断点下载,该断点下载可应用于浏览器

来源: javaer 分享于  点击 39170 次 点评:111

Java 实现的断点下载,Java实现断点下载,该断点下载可应用于浏览器


该断点下载可应用于浏览器或者迅雷等下载工具的下载,实现方式有多种多样的,本文只研究了单线程的下载,迅雷等下载工具会自动将下载资源分块并记录每块的起始位置,然后根据系统性能,起多线程下载。

基本原理

从Request Header的Range信息里面获取已经下载的文件大小,然后创建response的outputstream 向客户端(浏览器或者迅雷等下载工具)写,写的时候又利用header里面的“Content-Range”, 让客户端知道从哪个位置开始写;

读取网络资源方面,利用HttpClient模拟request请求,发起post或者get请求,只是这个请求跟一般请求有点不一样:需要带上Range信息,告诉程序该从哪个位置开始读数据。

需要使用的Java 组件 HttpServletRequest / ResponseHttpClientServletOutputStreamBufferedInputStream代码实现
    /**          * @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的输出流程来向客户端提供下载功能,而不是简单的把数据写入到某个具体的文件,核心代码:out = response.getOutputStream();

 - 头信息里面"Range" 和 "Conent-Range" 等信息的处理;

-迅雷等多线程分块下载客户端下载的处理:还是要处理好"Range"和"Conent-Range"等头部信息,迅雷会自动将文件内容分块、记录起始位置。

来自:http://blog.csdn.net/alli0968/article/details/47337349

相关栏目:

用户点评