多线程下载(转)
原文是在52上下载的。
感觉我们对IO和URL这些不够熟悉.很简单的.之前自己尝试过,感觉复杂化了,但也不好说.其实最想要的还是类似idm这种多线程,呵呵.
代码:
package com.test_four; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class Demo { public static int threadCount = 3; public static void main(String[] args) throws Exception { // 1.连接服务器,获取一个文件,获取一个文件,获取文件的长度,在本地创建一个大小和服务器文件一样大的临时文件 String path = "https://admdownload.adobe.com/bin/livebeta/flashplayer24_va_install.exe"; URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); int code = conn.getResponseCode(); if (code == 200) { //服务器返回的数据的长度 实际上就是文件的长度 int length = conn.getContentLength(); System.out.println("文件总长度:" + length); // 在客户端本地创建出来一个大小跟服务器端文件一样的临时文件 RandomAccessFile raf = new RandomAccessFile("xxx.exe", "rw"); // 指定创建的这个文件的长度 raf.setLength(length); raf.close(); // 假设是三个线程去下载资源 // 平均每一个线程下载的文件的大小 int blockSize = length/threadCount; for(int threadId = 1;threadId<=threadCount;threadId++){ // 第一个线程下载的开始位置 int startIndex = (threadId -1)*blockSize; int endIndex = threadId*blockSize -1; if (threadId == threadCount) {//最后一个线程下载的长度要稍微长一点 endIndex = length; } System.out.println("线程:"+ threadId +"下载:---"+ startIndex +"--->"+ endIndex); new DownloadThread(path, threadId, startIndex, endIndex).start(); } } else { System.out.println("服务器错误"); } } public static class DownloadThread extends Thread{ private int threadId; private int startIndex; private int endIndex; private String path; @Override public void run() { try { URL url = new URL(path); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(5000); connection.setRequestMethod("GET"); // 重要:请求服务器下载部分的文件指定文件的位置 connection.setRequestProperty("Range","bytes=" + startIndex +"-" +endIndex); int code = connection.getResponseCode();//从服务器请求全部资源200 ok 如果从服务器请求部分资源206 ok // System.out.println("code:" + code); InputStream is =connection.getInputStream();//已经设置了请求的位置,返回的是当前位置对应的文件的输入流 RandomAccessFile raf = new RandomAccessFile("xxx.exe", "rw"); raf.seek(startIndex);//随机写文件的时候从哪个位置开始写 int len = 0; byte[] buffer = new byte[1024]; while ((len = is.read(buffer))!=-1) { raf.write(buffer, 0, len); } is.close(); raf.close(); System.out.println("线程:"+threadId +"下载完毕"); } catch (IOException e) { e.printStackTrace(); } } /* * threadId 线程id * startIndex 线程下载的开始位置 * endIndex 线程下载的结束位置 * path 下载文件在服务器的路径 */ public DownloadThread(String path,int threadId, int startIndex, int endIndex) { super(); this.threadId = threadId; this.startIndex = startIndex; this.endIndex = endIndex; this.path = path; } } }