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

时间: 2024-10-10 04:55:20

Java 实现的断点下载的相关文章

Java之多线程断点下载的实现

RandomAccessFile类: 此类的实例支持对随机訪问文件的读取和写入.随机訪问文件的行为相似存储在文件系统中的一个大型 byte 数组. 存在指向该隐含数组.光标或索引,称为文件指针.输入操作从文件指针開始读取字节.并随着对字节的读取而前移此文件指针. 假设随机訪问文件以读取/写入模式创建,则输出操作也可用.输出操作从文件指针開始写入字节.并随着对字节的写入而前移此文件指针.写入隐含数组的当前末尾之后的输出操作导致该数组扩展.该文件指针能够通过 getFilePointer 方法读取.

Android/java http多线程断点下载(附源码)

先看下项目结构: http多线程断点下载涉及到 数据库,多线程和http请求等几个模块,东西不是很多,想弄清楚也不是很困难,接下来我和大家分享下我的做法. 一.先看MainActivity.java 成员变量,主要是一些下载过程的变量和handler private String path = "http://192.168.1.3:8080/wanmei/yama.apk"; private String sdcardPath; private int threadNum = 5;

Java实现多线程断点下载(下载过程中可以暂停)

线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配.不难理解,如果你线程多的话,那下载的越快. 现流行的下载软件都支持多线程,且支持中途暂停下载,再次开始时不会从头开始下载. 两种功能的实现步骤如下: (1)连接到下载资源文件时,首先判断资源文件大小,同步的在本地创建一个大小相同的临时文件用于存储下载数据. (2)根据线程数量确定每个线程所需下载的文

JAVA实现多线程断点下载

public class jions { public static int runnling=3; public static int threadcount=3; public static void main(String[]args) throws Exception{ String path="http://down9.869v.com/setup_445.exe"; URL url=new URL(path); HttpURLConnection con= (HttpURL

多线程断点下载原理(java代码实例演示)

其实多线程断点下载原理,很简单的,那么我们就来先了解下,如何实现多线程的断点下载,首先:你必须明白第一点,那么就是,什么是多线程下载,该知识点可以查看本博客上一篇文章,Android之多线程下载原理,断点下载呢,其实就是在这个的基础之上添加了一些东西,那么添加了什么东西了,现在来做一个详细的了解. 1.在下载的过程中,边下载,变用一个文件来记录下载的位置,也就是下载了多少的数据 1.创建文件 2.记录下载多少数据 3.存储数据 2.第二次下载的时候,就去读取文件中是否存有数据,读取上次下载的位置

Java多线程断点下载

多线程下载已经提高了下载的效率,但是当一些特殊情况发生的时候,我们需要对程序进行处理,这样效率会更高.比如,断电断网等造成下载中断,那么我们下一次又要重新开始下载,这样效率底下,所以我们可以考虑使用断点下载.其原理主要是把每次每个线程的下载状况(已经下载的位置)保存到文件,下次读取出来,从上一次下载的位置继续下载,这样就大大提高了下载的效率. 效果: 开始下载: 下载过程中: 下载过程中,系统临时文件保存已下载的位置: 下载完毕,系统清楚记录下载位置的临时文件: 附代码如下: 1 import

【Java EE 学习第22天 文件下载】【单线程下载】【单线程断点下载】【多线程下载】

一.文件下载简述 1.使用浏览器从网页上下载文件,Servlet需要增加一些响应头信息 (1)response.setContentType("application/force-download"); (2)response.setContentLength(fis.available()); (3)response.setHeader("Content-Disposition","attachment;filename="+filename)

JAVA下实现多线程断点下载

多线程断点下载:顾名思义是用多线程实现的,断点是当第三方因素(断电.断网等)中断下载时,下次下载可以继续上次下载的地方下载. 1.通过getContentLength可以获取要下载文件的大小,这样可以在本机上创建一个相同大小的文件用来下载. int fileLength = connection.getContentLength(); 2.由于是多线程,所以要给每一个线程均分分配要下载的位置. for(int i = 0; i < threadCount; i ++) { int startTh

java多线程断点下载原理(代码实例演示)

原文:http://www.open-open.com/lib/view/open1423214229232.html 其实多线程断点下载原理,很简单的,那么我们就来先了解下,如何实现多线程的断点下载,首先:你必须明白第一点,那么就是,什么是多线程下载,该知识点可以查看本博客上一篇文章,Android之多线程下载原理,断点下载呢,其实就是在这个的基础之上添加了一些东西,那么添加了什么东西了,现在来做一个详细的了解. 1.在下载的过程中,边下载,变用一个文件来记录下载的位置,也就是下载了多少的数据