多线程下载之断点续传采用随机文件读取流,HttpConnection实现
来源:互联网 发布:东安格利亚大学知乎 编辑:程序博客网 时间:2024/06/06 20:24
/**
*
*/
package com.l000phone.multithreaddown.advanced;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Description: 多线程从服器端下载资源演示(网络出现异常,需要进行断点续传)
* Copyright (c) , 2016, Jansonxu
* This program is protected by copyright laws.
* Program Name:Download.java
* Date: 2016-2-16
*
* @author 李阳
* @version : 1.0
*/
public class AdvancedDownload {
/** * @param args */public static void main(String[] args) { // 1、在客户端获得服务器资源的长度,根据此长度在客户端创建一个临时文件 try { URL url = new URL( "http://localhost:8080/ServerSide/file/VNC-5.1.1-Windows.exe"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { int resLen = conn.getContentLength(); System.out.println("要下载资源的长度是:" + resLen); RandomAccessFile raf = new RandomAccessFile(new File( "download/VNC-5.1.1-Windows.exe"), "rwd");// 创建临时文件 raf.setLength(resLen); raf.close();// 关闭资源 // 2、获得每个线程下载资源的开始和结束位置 // 3、开启多个线程从服务其下载资源,直到所有的线程执行完毕 int blockSize = resLen / 3;// 每个线程平均下载的长度 AdvancedDownload outer = new AdvancedDownload();// 外部类对象 // 创建文件对象(记录各个子线程下载的最终结果) File threadDownadStatusFile = new File( "download/finalStauts.txt"); if (!threadDownadStatusFile.exists()) { threadDownadStatusFile.createNewFile(); } for (int threadId = 1; threadId <= 3; threadId++) { // ①开始位置 int startPos = (threadId - 1) * blockSize; // ②结束位置 int endPos = threadId * blockSize - 1; if (threadId == 3) { endPos = resLen - 1; } // ③启动子线程下载 outer.new DownloadSonThread(startPos, endPos, url, threadId, threadDownadStatusFile).start(); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }}/** * 资源下载子线程 */private class DownloadSonThread extends Thread { private int startPos; private int endPos; private URL url; private int threadId; private File threadDownadStatusFile; public DownloadSonThread(int startPos, int endPos, URL url, int threadId, File threadDownadStatusFile) { super(); this.startPos = startPos; this.endPos = endPos; this.url = url; this.threadId = threadId; this.threadDownadStatusFile = threadDownadStatusFile; } @Override public void run() { // ①获得连接实例 try { HttpURLConnection conn = (HttpURLConnection) url .openConnection(); // 读取线程字节数记录文件中的数据,作为开始线程下载的开始位置 File file = new File("download/" + threadId + ".txt"); if (file.exists()) { BufferedReader br = new BufferedReader(new FileReader(file)); String startPosRecord = br.readLine(); startPos = Integer.parseInt(startPosRecord); br.close(); } // ②设置连接的属性为下载部分资源 conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); System.out.println("来自服务器端的状态码:" + conn.getResponseCode()); // ③从服务器获取资源,填充本地客户端的临时文件 if (conn.getResponseCode() == 206) {// 206:服务器端的资源是属于分段下载的、200:服务端所有的资源都发送给了客户端 // a)获得网络字节输入流 InputStream is = conn.getInputStream(); byte[] b = new byte[1024]; int len = 0; // b)将流中的数据写入到本地临时文件中 RandomAccessFile raf = new RandomAccessFile(new File( "download/VNC-5.1.1-Windows.exe"), "rwd");// 向临时文件中写入数据 raf.seek(startPos); int totalBytes = startPos;// 当前线程已经下载的字节数 while ((len = is.read(b)) != -1) { // seek移动指针偏移量,写入数据 raf.write(b, 0, len); totalBytes += len;// 累加目前已经下载的字节数 RandomAccessFile nowRecordLenFile = new RandomAccessFile( new File("download/" + threadId + ".txt"), "rwd"); nowRecordLenFile.write((totalBytes + "").getBytes()); nowRecordLenFile.close(); } raf.close(); System.out.println("线程" + threadId + "下载资源完毕...."); FileWriter fw = new FileWriter(threadDownadStatusFile, true); fw.write(threadId + "over"); fw.close(); } } catch (IOException e) { e.printStackTrace(); } finally { // 读取文件中的内容,若发现内容匹配: // 内容.contains("thread1over") 并且 内容.contains("thread2over") 并且 // 内容.contains("thread3over") // 就删除各个临时文件 BufferedReader br = null; try { br = new BufferedReader(new FileReader( threadDownadStatusFile)); String finalResultInfo = br.readLine(); if (finalResultInfo.contains("1over") && finalResultInfo.contains("2over") && finalResultInfo.contains("3over")) { for (int threadId = 1; threadId <= 3; threadId++) { new File("download/" + threadId + ".txt").delete(); } br.close(); new File("download/finalStauts.txt").delete(); System.out.println("恭喜!所有临时文件都已经删除掉了哦!..."); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }}
}
2 0
- 多线程下载之断点续传采用随机文件读取流,HttpConnection实现
- C#实现http多线程断点续传下载文件
- Android之 多线程下载、断点续传 实现
- Android之 多线程下载、断点续传 实现
- 采用多线程的方式实现文件下载
- HttpURLConnection方式下载文件之实现断点续传
- 构造HTTP消息体采用HttpConnection实现文件上传
- 消息机制之文件下载与断点续传,多线程下载
- 断点续传实现文件下载
- 多线程断点续传文件下载原理
- Android 文件多线程断点续传下载
- java 多线程文件下载,断点续传
- Java实现多线程下载、断点续传
- java多线程实现断点续传下载
- 利用HTTP协议实现文件下载的多线程断点续传
- 利用HTTP协议实现文件下载的多线程断点续传
- 以多线程、断点续传方式下载文件的实现
- Asp.net(c#)实现多线程断点续传下载大文件
- 深入理解Activity
- 多维数组
- 数组(一维数组)
- android studio创建第一个安卓程序加载html5页面(二)
- 结构体使用分析
- 多线程下载之断点续传采用随机文件读取流,HttpConnection实现
- 转:解决 unresolved external symbol 无法解析
- 【SPOJ-ARRAYSUB】subarrays【单调队列】
- 实现JTable的动态更新
- 读uCOSIII源码笔记
- java基础 内部类使用总结
- C语言文件操作函数大全
- Apache shiro 笔记整理之编程式授权
- Gartner诠释什么是真正的BI分析平台