使用Apache HttpClient实现多线程下载的小例子
来源:互联网 发布:秦国灭亡知乎 编辑:程序博客网 时间:2024/05/16 17:44
网上类似的文章很多,参考了很多人的,大部分人都是用URLConnection写的。
原理一:HTTP多线程下载原理
1、发送一个含有Rang头的Head请求,如果返回状态码为206,则允许多线程下载
原理二:多线程下载原理
1、使用HttpClient的Head请求获取请求文件的信息
2、发送一个Rang的Head请求判断是否允许多线程下载
3、通过主任务创建多个分段下载线程,分段下载文件,然后用Java的随机读写文件类保存下载的内容
(等有时间了再添加内容吧,先简单写这么多)
调度功能代码片段
- /**
- * 开始下载
- * @throws Exception
- */
- public void startDown() throws Exception{
- HttpClient httpClient = new DefaultHttpClient();
- try {
- //获取下载文件信息
- getDownloadFileInfo(httpClient);
- //启动多个下载线程
- startDownloadThread();
- //开始监视下载数据
- monitor();
- } catch (Exception e) {
- throw e;
- } finally {
- httpClient.getConnectionManager().shutdown();
- }
- }
- /**
- * 获取下载文件信息
- */
- private void getDownloadFileInfo(HttpClient httpClient) throws IOException,
- ClientProtocolException, Exception {
- HttpHead httpHead = new HttpHead(url);
- HttpResponse response = httpClient.execute(httpHead);
- //获取HTTP状态码
- int statusCode = response.getStatusLine().getStatusCode();
- if(statusCode != 200) throw new Exception("资源不存在!");
- if(getDebug()){
- for(Header header : response.getAllHeaders()){
- System.out.println(header.getName()+":"+header.getValue());
- }
- }
- //Content-Length
- Header[] headers = response.getHeaders("Content-Length");
- if(headers.length > 0)
- contentLength = Long.valueOf(headers[0].getValue());
- httpHead.abort();
- httpHead = new HttpHead(url);
- httpHead.addHeader("Range", "bytes=0-"+(contentLength-1));
- response = httpClient.execute(httpHead);
- if(response.getStatusLine().getStatusCode() == 206){
- acceptRanges = true;
- }
- httpHead.abort();
- }
- /**
- * 启动多个下载线程
- * @throws IOException
- * @throws FileNotFoundException
- */
- private void startDownloadThread() throws IOException,
- FileNotFoundException {
- //创建下载文件
- File file = new File(localPath);
- file.createNewFile();
- RandomAccessFile raf = new RandomAccessFile(file, "rw");
- raf.setLength(contentLength);
- raf.close();
- //定义下载线程事件实现类
- DownloadThreadListener listener = new DownloadThreadListener() {
- public void afterPerDown(DownloadThreadEvent event) {
- //下载完一个片段后追加已下载字节数
- synchronized (object) {
- DownloadTask.this.receivedCount += event.getCount();
- }
- }
- public void downCompleted(DownloadThreadEvent event) {
- //下载线程执行完毕后从主任务中移除
- threads.remove(event.getTarget());
- if(getDebug()){
- System.out.println("剩余线程数:"+threads.size());
- }
- }
- };
- //不支持多线程下载时
- if (!acceptRanges) {
- if(getDebug()){
- System.out.println("该地址不支持多线程下载");
- }
- //定义普通下载
- DownloadThread thread = new DownloadThread(url, 0, contentLength, file, false);
- thread.addDownloadListener(listener);
- thread.start();
- threads.add(thread);
- return;
- }
- //每个请求的大小
- long perThreadLength = contentLength / threadCount + 1;
- long startPosition = 0;
- long endPosition = perThreadLength;
- //循环创建多个下载线程
- do{
- if(endPosition >= contentLength)
- endPosition = contentLength - 1;
- DownloadThread thread = new DownloadThread(url, startPosition, endPosition, file);
- thread.addDownloadListener(listener);
- thread.start();
- threads.add(thread);
- startPosition = endPosition + 1;//此处加 1,从结束位置的下一个地方开始请求
- endPosition += perThreadLength;
- } while (startPosition < contentLength);
- }
- /**
- * 开始下载
- * @throws Exception
- */
- public void startDown() throws Exception{
- HttpClient httpClient = new DefaultHttpClient();
- try {
- //获取下载文件信息
- getDownloadFileInfo(httpClient);
- //启动多个下载线程
- startDownloadThread();
- //开始监视下载数据
- monitor();
- } catch (Exception e) {
- throw e;
- } finally {
- httpClient.getConnectionManager().shutdown();
- }
- }
- /**
- * 获取下载文件信息
- */
- private void getDownloadFileInfo(HttpClient httpClient) throws IOException,
- ClientProtocolException, Exception {
- HttpHead httpHead = new HttpHead(url);
- HttpResponse response = httpClient.execute(httpHead);
- //获取HTTP状态码
- int statusCode = response.getStatusLine().getStatusCode();
- if(statusCode != 200) throw new Exception("资源不存在!");
- if(getDebug()){
- for(Header header : response.getAllHeaders()){
- System.out.println(header.getName()+":"+header.getValue());
- }
- }
- //Content-Length
- Header[] headers = response.getHeaders("Content-Length");
- if(headers.length > 0)
- contentLength = Long.valueOf(headers[0].getValue());
- httpHead.abort();
- httpHead = new HttpHead(url);
- httpHead.addHeader("Range", "bytes=0-"+(contentLength-1));
- response = httpClient.execute(httpHead);
- if(response.getStatusLine().getStatusCode() == 206){
- acceptRanges = true;
- }
- httpHead.abort();
- }
- /**
- * 启动多个下载线程
- * @throws IOException
- * @throws FileNotFoundException
- */
- private void startDownloadThread() throws IOException,
- FileNotFoundException {
- //创建下载文件
- File file = new File(localPath);
- file.createNewFile();
- RandomAccessFile raf = new RandomAccessFile(file, "rw");
- raf.setLength(contentLength);
- raf.close();
- //定义下载线程事件实现类
- DownloadThreadListener listener = new DownloadThreadListener() {
- public void afterPerDown(DownloadThreadEvent event) {
- //下载完一个片段后追加已下载字节数
- synchronized (object) {
- DownloadTask.this.receivedCount += event.getCount();
- }
- }
- public void downCompleted(DownloadThreadEvent event) {
- //下载线程执行完毕后从主任务中移除
- threads.remove(event.getTarget());
- if(getDebug()){
- System.out.println("剩余线程数:"+threads.size());
- }
- }
- };
- //不支持多线程下载时
- if (!acceptRanges) {
- if(getDebug()){
- System.out.println("该地址不支持多线程下载");
- }
- //定义普通下载
- DownloadThread thread = new DownloadThread(url, 0, contentLength, file, false);
- thread.addDownloadListener(listener);
- thread.start();
- threads.add(thread);
- return;
- }
- //每个请求的大小
- long perThreadLength = contentLength / threadCount + 1;
- long startPosition = 0;
- long endPosition = perThreadLength;
- //循环创建多个下载线程
- do{
- if(endPosition >= contentLength)
- endPosition = contentLength - 1;
- DownloadThread thread = new DownloadThread(url, startPosition, endPosition, file);
- thread.addDownloadListener(listener);
- thread.start();
- threads.add(thread);
- startPosition = endPosition + 1;//此处加 1,从结束位置的下一个地方开始请求
- endPosition += perThreadLength;
- } while (startPosition < contentLength);
- }
/** * 开始下载 * @throws Exception */public void startDown() throws Exception{HttpClient httpClient = new DefaultHttpClient();try {//获取下载文件信息getDownloadFileInfo(httpClient);//启动多个下载线程startDownloadThread();//开始监视下载数据monitor();} catch (Exception e) {throw e;} finally {httpClient.getConnectionManager().shutdown();}}/** * 获取下载文件信息 */private void getDownloadFileInfo(HttpClient httpClient) throws IOException,ClientProtocolException, Exception {HttpHead httpHead = new HttpHead(url);HttpResponse response = httpClient.execute(httpHead);//获取HTTP状态码int statusCode = response.getStatusLine().getStatusCode();if(statusCode != 200) throw new Exception("资源不存在!");if(getDebug()){for(Header header : response.getAllHeaders()){System.out.println(header.getName()+":"+header.getValue());}}//Content-LengthHeader[] headers = response.getHeaders("Content-Length");if(headers.length > 0)contentLength = Long.valueOf(headers[0].getValue());httpHead.abort();httpHead = new HttpHead(url);httpHead.addHeader("Range", "bytes=0-"+(contentLength-1));response = httpClient.execute(httpHead);if(response.getStatusLine().getStatusCode() == 206){acceptRanges = true;}httpHead.abort();}/** * 启动多个下载线程 * @throws IOException * @throws FileNotFoundException */private void startDownloadThread() throws IOException,FileNotFoundException {//创建下载文件File file = new File(localPath);file.createNewFile();RandomAccessFile raf = new RandomAccessFile(file, "rw");raf.setLength(contentLength);raf.close();//定义下载线程事件实现类DownloadThreadListener listener = new DownloadThreadListener() {public void afterPerDown(DownloadThreadEvent event) {//下载完一个片段后追加已下载字节数synchronized (object) {DownloadTask.this.receivedCount += event.getCount();}}public void downCompleted(DownloadThreadEvent event) {//下载线程执行完毕后从主任务中移除threads.remove(event.getTarget());if(getDebug()){System.out.println("剩余线程数:"+threads.size());}}};//不支持多线程下载时if (!acceptRanges) {if(getDebug()){System.out.println("该地址不支持多线程下载");}//定义普通下载DownloadThread thread = new DownloadThread(url, 0, contentLength, file, false);thread.addDownloadListener(listener);thread.start();threads.add(thread);return;}//每个请求的大小long perThreadLength = contentLength / threadCount + 1;long startPosition = 0;long endPosition = perThreadLength;//循环创建多个下载线程do{if(endPosition >= contentLength)endPosition = contentLength - 1;DownloadThread thread = new DownloadThread(url, startPosition, endPosition, file);thread.addDownloadListener(listener);thread.start();threads.add(thread);startPosition = endPosition + 1;//此处加 1,从结束位置的下一个地方开始请求endPosition += perThreadLength;} while (startPosition < contentLength);}
分段下载线程代码片段:
- /**
- * 现在过程代码
- */
- public void run() {
- if(DownloadTask.getDebug()){
- System.out.println("Start:" + startPosition + "-" +endPosition);
- }
- HttpClient httpClient = new DefaultHttpClient();
- try {
- HttpGet httpGet = new HttpGet(url);
- if(isRange){//多线程下载
- httpGet.addHeader("Range", "bytes="+startPosition+"-"+endPosition);
- }
- HttpResponse response = httpClient.execute(httpGet);
- int statusCode = response.getStatusLine().getStatusCode();
- if(DownloadTask.getDebug()){
- for(Header header : response.getAllHeaders()){
- System.out.println(header.getName()+":"+header.getValue());
- }
- System.out.println("statusCode:" + statusCode);
- }
- if(statusCode == 206 || (statusCode == 200 && !isRange)){
- InputStream inputStream = response.getEntity().getContent();
- //创建随机读写类
- RandomAccessFile outputStream = new RandomAccessFile(file, "rw");
- //跳到指定位置
- outputStream.seek(startPosition);
- int count = 0;byte[] buffer=new byte[1024];
- while((count = inputStream.read(buffer, 0, buffer.length))>0){
- outputStream.write(buffer, 0, count);
- //触发下载事件
- fireAfterPerDown(new DownloadThreadEvent(this,count));
- }
- outputStream.close();
- }
- httpGet.abort();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- //触发下载完成事件
- fireDownCompleted(new DownloadThreadEvent(this, endPosition));
- if(DownloadTask.getDebug()){
- System.out.println("End:" + startPosition + "-" +endPosition);
- }
- httpClient.getConnectionManager().shutdown();
- }
- }
- /**
- * 现在过程代码
- */
- public void run() {
- if(DownloadTask.getDebug()){
- System.out.println("Start:" + startPosition + "-" +endPosition);
- }
- HttpClient httpClient = new DefaultHttpClient();
- try {
- HttpGet httpGet = new HttpGet(url);
- if(isRange){//多线程下载
- httpGet.addHeader("Range", "bytes="+startPosition+"-"+endPosition);
- }
- HttpResponse response = httpClient.execute(httpGet);
- int statusCode = response.getStatusLine().getStatusCode();
- if(DownloadTask.getDebug()){
- for(Header header : response.getAllHeaders()){
- System.out.println(header.getName()+":"+header.getValue());
- }
- System.out.println("statusCode:" + statusCode);
- }
- if(statusCode == 206 || (statusCode == 200 && !isRange)){
- InputStream inputStream = response.getEntity().getContent();
- //创建随机读写类
- RandomAccessFile outputStream = new RandomAccessFile(file, "rw");
- //跳到指定位置
- outputStream.seek(startPosition);
- int count = 0;byte[] buffer=new byte[1024];
- while((count = inputStream.read(buffer, 0, buffer.length))>0){
- outputStream.write(buffer, 0, count);
- //触发下载事件
- fireAfterPerDown(new DownloadThreadEvent(this,count));
- }
- outputStream.close();
- }
- httpGet.abort();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- //触发下载完成事件
- fireDownCompleted(new DownloadThreadEvent(this, endPosition));
- if(DownloadTask.getDebug()){
- System.out.println("End:" + startPosition + "-" +endPosition);
- }
- httpClient.getConnectionManager().shutdown();
- }
- }
/** * 现在过程代码 */public void run() {if(DownloadTask.getDebug()){System.out.println("Start:" + startPosition + "-" +endPosition);}HttpClient httpClient = new DefaultHttpClient();try {HttpGet httpGet = new HttpGet(url);if(isRange){//多线程下载httpGet.addHeader("Range", "bytes="+startPosition+"-"+endPosition);}HttpResponse response = httpClient.execute(httpGet);int statusCode = response.getStatusLine().getStatusCode();if(DownloadTask.getDebug()){for(Header header : response.getAllHeaders()){System.out.println(header.getName()+":"+header.getValue());}System.out.println("statusCode:" + statusCode);}if(statusCode == 206 || (statusCode == 200 && !isRange)){InputStream inputStream = response.getEntity().getContent();//创建随机读写类RandomAccessFile outputStream = new RandomAccessFile(file, "rw");//跳到指定位置outputStream.seek(startPosition);int count = 0;byte[] buffer=new byte[1024];while((count = inputStream.read(buffer, 0, buffer.length))>0){outputStream.write(buffer, 0, count);//触发下载事件fireAfterPerDown(new DownloadThreadEvent(this,count));}outputStream.close();}httpGet.abort();} catch (Exception e) {e.printStackTrace();} finally {//触发下载完成事件fireDownCompleted(new DownloadThreadEvent(this, endPosition));if(DownloadTask.getDebug()){System.out.println("End:" + startPosition + "-" +endPosition);}httpClient.getConnectionManager().shutdown();}}
附件说明:
1、Download.jar为编译好的可运行程序
2、Download.zip为Eclipse项目文件
3、运行截图
- Download.jar (928.1 KB)
- 下载次数: 44
- DownLoad.zip (832.5 KB)
- 下载次数: 70
0 0
- 使用Apache HttpClient实现多线程下载的小例子
- 使用Apache HttpClient实现多线程下载的小例子
- apache httpclient 使用例子
- 什么是httpclient?& Httpclient使用前提----下载org.apache.commons.httpclient,导入Httpclient的jar包
- 使用Apache中的HttpClient的实例CloseableHttpClient的一个例子
- 使用HttpClient实现文件的下载
- apache HttpClient的使用
- Apache的HttpClient创建CloseableHttpClient的例子
- org.apache.commons.httpclient.HttpClient的使用
- org.apache.commons.httpclient.HttpClient的使用
- android使用Apache HttpClient实现get/post的请求
- JQuery的AJAX实现文件下载的小例子
- 多线程下载的代码例子
- 多线程的一个小例子
- 多线程通信的小例子
- 一个使用DownloadManager下载文件的小例子
- 使用Apache Httpclient访问Spring rest接口下载文件
- HttpClient读取页面的使用例子
- Struts表单验证field-validator的类型type
- jquery select2使用心得
- jQuery插件开发入门与最佳实践
- 局域网简介
- maven-Maven的依赖特性和冲突解决
- 使用Apache HttpClient实现多线程下载的小例子
- jmeter学习(一)简单的接口测试
- java无法转化时间问题
- [LVS] 负载均衡的方式和选择
- 欢迎使用CSDN-markdown编辑器
- Java Web day(6)之jsp&Cookie&HttpSession基础
- 学习笔记——IOC
- oracle 函数 实现行转列
- ARM命名规则