package cn.xl.c3; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class DownloadTask { public void download(String urlStr, String charset) { this.charset = charset; long contentLength = 0; CountDownLatch latch = new CountDownLatch(threadNum); long[] startPos = new long[threadNum]; long endPos = 0; try { // ��url�л�����ص��ļ���ʽ������ //String fileSeparator = System.getProperty("file.separator"); this.fileName = urlStr.substring(urlStr.lastIndexOf("/") + 1); this.url = new URL(urlStr); URLConnection con = url.openConnection(); setHeader(con); // �õ�content�ij��� contentLength = con.getContentLength(); // ��context��ΪthreadNum�εĻ���ÿ�εij��ȡ� this.threadLength = contentLength / threadNum; // ��һ�������������ص���ʱ�ļ������öϵ㣬������µ�������������Ŀ���ļ����ڵ�4����˵���� startPos = setThreadBreakpoint(fileDir, fileName, contentLength, startPos); //�ڶ������ֶ���߳������ļ� ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < threadNum; i++) { // �������߳��������������ݣ�ÿ�����ݵ���ʼλ��Ϊ(threadLength * i + �����س���) startPos[i] += threadLength * i; /**//*�������̵߳���ֹλ�ã������һ���̼߳�Ϊ(threadLength * (i + 1) - 1) ���һ���̵߳���ֹλ�ü�Ϊ�������ݵij���*/ if (i == threadNum - 1) { endPos = contentLength; } else { endPos = threadLength * (i + 1) - 1; } // �������̣߳���ִ�С� ChildThread thread = new ChildThread(this, latch, i, startPos[i], endPos); childThreads[i] = thread; exec.execute(thread); } try { // �ȴ�CountdownLatch�ź�Ϊ0����ʾ�������̶߳������� latch.await(); exec.shutdown(); // ���������ѷֶ�������������ʱ�ļ��е�����д��Ŀ���ļ��С��ڵ�3����˵���� tempFileToTargetFile(childThreads); } catch (InterruptedException e) { e.printStackTrace(); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } ///////// private long[] setThreadBreakpoint(String fileDir2, String fileName2, long contentLength, long[] startPos) { File file = new File(fileDir + fileName); long localFileSize = file.length(); if (file.exists()) { System.out.println("file " + fileName + " has exists!"); // ���ص�Ŀ���ļ��Ѵ��ڣ��ж�Ŀ���ļ��Ƿ����� if (localFileSize < contentLength) { System.out.println("Now download continue "); // ����Ŀ���ļ���������ʱ�ļ������öϵ��λ�ã���ÿ����ʱ�ļ��ij��� File tempFileDir = new File(fileDir); File[] files = tempFileDir.listFiles(); for (int k = 0; k < files.length; k++) { String tempFileName = files[k].getName(); // ��ʱ�ļ���������ʽΪ��Ŀ���ļ���+"_"+��� if (tempFileName != null && files[k].length() > 0 && tempFileName.startsWith(fileName + "_")) { int fileLongNum = Integer.parseInt(tempFileName .substring(tempFileName.lastIndexOf("_") + 1, tempFileName.lastIndexOf("_") + 2)); // Ϊÿ���߳����������ص�λ�� startPos[fileLongNum] = files[k].length(); } } } } else { // ������ص�Ŀ���ļ������ڣ��򴴽����ļ� try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } return startPos; } //// private void setHeader(URLConnection con) { con.setRequestProperty("User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 Ubuntu/8.04 (hardy) Firefox/3.0.3"); con.setRequestProperty("Accept-Language", "en-us,en; q=0.7,zh-cn; q=0.3"); con.setRequestProperty("Accept-Encoding", "aa"); con.setRequestProperty("Accept-Charset", "ISO-8859-1,utf-8; q=0.7,*; q=0.7"); con.setRequestProperty("Keep-Alive", "300"); con.setRequestProperty("Connection", "keep-alive"); con.setRequestProperty("If-Modified-Since", "Fri, 02 Jan 2009 17:00:05 GMT"); con.setRequestProperty("If-None-Match", "\"1261d8-4290-df64d224\""); con.setRequestProperty("Cache-Control", "max-age=0"); con.setRequestProperty("Referer", "http://http://www.bt285.cn"); } /// private void tempFileToTargetFile(ChildThread[] childThreads) { try { BufferedOutputStream outputStream = new BufferedOutputStream( new FileOutputStream(fileDir + fileName)); // �����������̴߳�������ʱ�ļ�����˳�����������д��Ŀ���ļ��� for (int i = 0; i < threadNum; i++) { if (statusError) { for (int k = 0; k < threadNum; k++) { if (childThreads[k].tempFile.length() == 0) childThreads[k].tempFile.delete(); } System.out.println("�����������񲻳ɹ��������������߳�����"); break; } BufferedInputStream inputStream = new BufferedInputStream( new FileInputStream(childThreads[i].tempFile)); System.out.println("Now is file " + childThreads[i].id); int len = 0; int count = 0; byte[] b = new byte[1024]; while ((len = inputStream.read(b)) != -1) { count += len; outputStream.write(b, 0, len); if ((count % 5000) == 0) { outputStream.flush(); } // b = new byte[1024]; } inputStream.close(); // ɾ����ʱ�ļ� if (childThreads[i].status == ChildThread.STATUS_HAS_FINISHED) { childThreads[i].tempFile.delete(); } } outputStream.flush(); outputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //////// class ChildThread extends Thread { public static final int STATUS_HASNOT_FINISHED = 0; public static final int STATUS_HAS_FINISHED = 1; public static final int STATUS_HTTPSTATUS_ERROR = 2; private DownloadTask task; private int id; private long startPosition; private long endPosition; private final CountDownLatch latch; private File tempFile = null; // �߳�״̬�� private int status = ChildThread.STATUS_HASNOT_FINISHED; public ChildThread(DownloadTask task, CountDownLatch latch, int id, long startPos, long endPos) { super(); this.task = task; this.id = id; this.startPosition = startPos; this.endPosition = endPos; this.latch = latch; try { tempFile = new File(this.task.fileDir + this.task.fileName + "_" + id); if(!tempFile.exists()){ tempFile.createNewFile(); } } catch (IOException e) { e.printStackTrace(); } } public void run() { System.out.println("Thread " + id + " run "); HttpURLConnection con = null; InputStream inputStream = null; BufferedOutputStream outputStream = null; int count = 0; long threadDownloadLength = endPosition - startPosition; try { outputStream = new BufferedOutputStream(new FileOutputStream(tempFile.getPath(), true)); } catch (FileNotFoundException e2) { e2.printStackTrace(); } for(; ; ){ startPosition += count; try { // ��URLConnection con = (HttpURLConnection) task.url.openConnection(); setHeader(con); con.setAllowUserInteraction(true); // �������ӳ�ʱʱ��Ϊ10000ms con.setConnectTimeout(10000); // ���ö�ȡ���ݳ�ʱʱ��Ϊ10000ms con.setReadTimeout(10000); if(startPosition < endPosition){ // �����������ݵ���ֹ���� con.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition); System.out.println("Thread " + id + " startPosition is " + startPosition); System.out.println("Thread " + id + " endPosition is " + endPosition); // �ж�http status�Ƿ�ΪHTTP/1.1 206 Partial Content����200 OK // ���������������״̬����status��ΪSTATUS_HTTPSTATUS_ERROR if (con.getResponseCode() != HttpURLConnection.HTTP_OK && con.getResponseCode() != HttpURLConnection.HTTP_PARTIAL) { System.out.println("Thread " + id + ": code = " + con.getResponseCode() + ", status = " + con.getResponseMessage()); status = ChildThread.STATUS_HTTPSTATUS_ERROR; this.task.statusError = true; outputStream.close(); con.disconnect(); System.out.println("Thread " + id + " finished."); latch.countDown(); break; } inputStream = con.getInputStream(); int len = 0; byte[] b = new byte[1024]; while ((len = inputStream.read(b)) != -1) { outputStream.write(b, 0, len); count += len; // ÿ����5000��byte����������flushһ�� if(count % 5000 == 0){ outputStream.flush(); } } System.out.println("count is " + count); if(count >= threadDownloadLength){ //hasFinished = true; } outputStream.flush(); outputStream.close(); inputStream.close(); con.disconnect(); } this.status = this.STATUS_HAS_FINISHED; //System.out.println("Thread " + id + " finished."); latch.countDown(); break; } catch (IOException e) { try { outputStream.flush(); TimeUnit.SECONDS.sleep(getSleepSeconds()); } catch (InterruptedException e1) { e1.printStackTrace(); } catch (IOException e2) { e2.printStackTrace(); } continue; } } } } public DownloadTask(int threadNum){ childThreads= new ChildThread[threadNum]; this.threadNum = threadNum; } private String charset; private int threadNum; private String fileName; private URL url; private Long threadLength; private String fileDir; private ChildThread[] childThreads ; private boolean statusError; private int SleepSeconds; public String getCharset() { return charset; } public void setCharset(String charset) { this.charset = charset; } public int getThreadNum() { return threadNum; } public void setThreadNum(int threadNum) { this.threadNum = threadNum; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public URL getUrl() { return url; } public void setUrl(URL url) { this.url = url; } public Long getThreadLength() { return threadLength; } public void setThreadLength(Long threadLength) { this.threadLength = threadLength; } public String getFileDir() { return fileDir; } public void setFileDir(String fileDir) { this.fileDir = fileDir; } public boolean isStatusError() { return statusError; } public void setStatusError(boolean statusError) { this.statusError = statusError; } public int getSleepSeconds() { return SleepSeconds; } public void setSleepSeconds(int sleepSeconds) { SleepSeconds = sleepSeconds; } }