java 实现文件的断点续传(文件的分段下载)
?
断点续传的原理:
把一个文件分为n个小文件,程序分n个线程去下载每一个小文件。阅读有关资料,IE浏览器传递给服务端的时候可以传递一个请求信息"Range":如:RANGE: bytes=2000070- ?一看就知道告诉服务器下载的时候从2000070字节开始下载。值得注意的是response.getResponseCode()为206,不再是200了。
?
上代码:
?
/** * 下载工具类 * * @author aokunsang * */public class FileDownloader {private HttpURLConnection conn;public static void main(String[] args) throws Exception {FileDownloader load = new FileDownloader();load.download();}/** * 开始下载 */public void download() throws Exception {HttpConnect connect = new HttpConnect(1);int fileSize = 0, threadSize = 3; // 文件长度和线程数conn = connect.initConnction();conn.connect();if (conn.getResponseCode() == 200) {fileSize = conn.getContentLength();conn.disconnect();}int perthThreadSize = fileSize / 3 + 1; //每个线程需要下载的文件大小RandomAccessFile raf = new RandomAccessFile(new File("D://ca.mp3"), "rw");raf.setLength(fileSize);raf.close();long startTime = System.currentTimeMillis();for (int i = 0; i < threadSize; i++) {int startpos = i * perthThreadSize; //线程开始下载的位置RandomAccessFile raff = new RandomAccessFile(new File("D://ca.mp3"), "rw");raff.seek(startpos);new myThread(startpos, perthThreadSize, i, raff).start();}long endTime = System.currentTimeMillis();while(Thread.activeCount()>1){} //防止main线程结束而导致下载线程被销毁System.out.println("--------------下载完成,共耗时:"+(endTime-startTime)/(60*1000)+"分钟--------");}class myThread extends Thread {private int startpos;private int perThreadSize;private int threadId;private RandomAccessFile raf;public myThread(int startpos, int perThreadSize, int threadId,RandomAccessFile raf) {this.startpos = startpos;this.perThreadSize = perThreadSize;this.threadId = threadId;this.raf = raf;}@Overridepublic void run() {HttpConnect connect = new HttpConnect(0);HttpURLConnection con = connect.initConnction();con.setRequestProperty("Range", "bytes=" + this.startpos + "-");try {InputStream is = con.getInputStream();byte[] bt = new byte[1024];int length = 0;int len = 0;while (length < this.perThreadSize && (len = is.read(bt)) != -1) {raf.write(bt, 0, len);length += len;}raf.close();is.close();System.out.println("线程"+threadId+"完成!");} catch (Exception e) {e.printStackTrace();}}}class HttpConnect {private int flag;public HttpConnect(int flag) {this.flag = flag;}public HttpURLConnection initConnction() {HttpURLConnection connection = null;try {URL url = new URL(HttpConnectParams.URLSTRING.content);connection = (HttpURLConnection) url.openConnection();connection.setConnectTimeout(Integer.parseInt(HttpConnectParams.CONNECTTIEMEDOUT.content));connection.setRequestMethod(HttpConnectParams.POST.content);connection.setRequestProperty(HttpConnectParams.ACCECT.header,HttpConnectParams.ACCECT.content);connection.setRequestProperty(HttpConnectParams.ACCECT_LANGAGE.header,HttpConnectParams.ACCECT_LANGAGE.content);connection.setRequestProperty(HttpConnectParams.CHARSET.header,HttpConnectParams.CHARSET.content);if (flag == 1) {connection.setRequestProperty(HttpConnectParams.KEEPCONNECT.header,HttpConnectParams.KEEPCONNECT.content);}} catch (Exception e) {connection = null;}return connection;}}}?
一/**
* HTTP请求的一些常量信息 * @author aokunsang * */public enum HttpConnectParams {/** * URL地址(mp3格式的音乐文件) */URLSTRING("http://www.61mp3.cn/music/%B6%F9%CD%AF%B8%E8%C7%FA/%CA%AE%B6%FE%C9%FA%D0%A4%B8%E8.mp3"),/** * 请求的方式 */POST("GET"),/** * 请求的格式 */ACCECT("Accept","image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"),/** * 请求的语言 */ACCECT_LANGAGE("Accept-Language","zh-CN"),/** * 请求的字符集编码 */CHARSET("Charset","UTF-8"),/** * 链接的超时数 */CONNECTTIEMEDOUT("5000"),/** * 保持链接 */KEEPCONNECT("Connection","Keep-Alive");public String header; //标题public String content; //内容private HttpConnectParams(String header,String content) {this.header = header;this.content = content;}private HttpConnectParams(String content){this.content = content;}}??