Java多线程下载
2012-09-10 10:22
369 查看
package org.yang.utils; /** * @author 杨志永 * email ljy520zhiyong@163.com * QQ 929168233 * Date 2012-9-10 */ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class MultiDownload implements Runnable { /** threadId 表示当前线程的Id .只能外界只能获取不能设置 */ private int threadId; /** threadNumbers 表示用多少条线程来下载. 外界可以设置下载的线程数,默认为5条线程。可以get和set */ private int threadNumbers = 5; /** 每条线程要下载的块大小,单位为byte。只能外界只能获取不能设置 */ private int blockSize; /** url 表示网络文件的URL地址的字符串表示形式 . 只能从外界设置(set),设置完后可以get */ private String url; /** savePathDir 表示要保存的本地路径目录 ,必须要设置。注意是目录 */ private String savePathDir; /** saveFile 表示要保存的本地文件 */ private File saveFile; /** fileName 表示文件名 */ private String fileName; public void setFileName(String fileName) { this.fileName = fileName; } public int getThreadId() { return threadId; } public int getThreadNumbers() { return threadNumbers; } public void setThreadNumbers(int threadNumbers) { this.threadNumbers = threadNumbers; } public int getBlockSize() { return blockSize; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getSavePathDir() { return savePathDir; } public void setSavePathDir(String savePathDir) { this.savePathDir = savePathDir; } public File getSaveFile() { return saveFile; } public void setSaveFile(File saveFile) { this.saveFile = saveFile; } public MultiDownload() { } /** * * @param threadId * 当前线程的Id * @param blockSize * 每条线程要下载的大小,单位为byte * @param url * 网络资源的url字符串 * @param saveFile * 要保存的路径 */ public MultiDownload(int threadId, int blockSize, String url, File saveFile) { super(); this.blockSize = blockSize; this.threadId = threadId; this.url = url; this.saveFile = saveFile; } public void startDownloadFile() throws IOException { /** 创建一个URL对象,参数为网络资源的字符串,用来与网络资源文件建立连接 */ URL url = new URL(this.url); /** 创建一个网络连接对象,并打开该连接 */ HttpURLConnection httpURLConnection = (HttpURLConnection) url .openConnection(); /** 设置超时 */ httpURLConnection.setConnectTimeout(5000); /** 设置请求方式,这里设置为GET */ httpURLConnection.setRequestMethod("GET"); try { /** 判断连接的返回状态码,200表示为正常状态 */ if (httpURLConnection.getResponseCode() == 200) { /** 获取网络文件的总大小,单位为byte */ int fileLength = httpURLConnection.getContentLength(); System.out.println("要下载的文件总大小为: " + fileLength + " bytes"); System.out.println("要下载的文件名为: " + this.getFileName()); /** 要保存为本地的路径表示的文件对象,为 保存的目录 + 网络文件的文件名 */ File saveFiles = new File(savePathDir + File.separator + this.getFileName()); /** 建立一个随机访问的文件对象,并设置它的大小为网络文件资源的文件总大小,即 fileLength */ RandomAccessFile randomAccessFile = new RandomAccessFile( saveFiles, "rwd"); randomAccessFile.setLength(fileLength); randomAccessFile.close(); /** 计算每条线程要下载的块大小blockSize,单位为byte */ int blockSize = fileLength % this.threadNumbers == 0 ? fileLength / this.threadNumbers : fileLength / this.threadNumbers + 1; System.out.println("每条线程要下载的文件大小为: " + blockSize + " bytes"); /** 启动所有线程来进行下载 */ for (int threadId = 0; threadId < this.threadNumbers; threadId++) { new Thread(new MultiDownload(threadId, blockSize, this.url, saveFiles)).start(); } } } catch (Exception e) { System.out.println("连接出错啦:第[" + this.threadId + "]条线程:"); e.printStackTrace(); } } @Override public void run() { System.out.println("第" + this.threadId + "条线程启动!"); /** start为每条线程从该位置开始下载 ,公式为 【开始位置=线程的ID*每条线程要下载的块大小】 */ int start = this.threadId * this.blockSize; /** * end 为每条线程从该位置结束下载 ,公式为 【结束位置=(线程的ID+1)*每条线程要下载的块大小 -1 * ,减1是因为文件的长度表示范围为:0~fileLength】 */ int end = (this.threadId + 1) * this.blockSize - 1; try { /** 打开要保存的本地文件的随机访问文件对象 */ RandomAccessFile randomAccessFile = new RandomAccessFile( this.saveFile, "rwd"); /** 将文件指针定位到每条线程的 start (即从start位置开始下载)的位置 */ randomAccessFile.seek(start); /** 打开连接 */ HttpURLConnection httpURLConnection = (HttpURLConnection) (new URL( this.url)).openConnection(); /** 设置超时 */ httpURLConnection.setConnectTimeout(5000); /** 设置请求方式 */ httpURLConnection.setRequestMethod("GET"); /** 设置从网络资源文件数据位置从start开始处,到end结束位置的文件数据 */ httpURLConnection.setRequestProperty("Range", "bytes=" + start + "-" + end); /** 如果请求成功,(成功的状态码为206) 则写入本地文件中 */ if (httpURLConnection.getResponseCode() == 206) { InputStream inputStream = httpURLConnection.getInputStream(); byte[] buffer = new byte[1024]; int length = 0; while ((length = inputStream.read(buffer)) != -1) { randomAccessFile.write(buffer, 0, length); } System.out.println("第" + this.threadId + "线程下载完毕"); } } catch (Exception e) { System.out.println("第" + this.threadId + "线程出错!"); e.printStackTrace(); } } /** 获取网络文件资源的文件名 */ public String getFileName() { /** 如果没有显式设置文件名,则从网络文件资源中设置 */ if ( fileName == null ) { return url.substring(url.lastIndexOf("/") + 1); } return fileName; } }
相关文章推荐
- Java多线程下载
- java多线程下载的实现示例
- java中多线程下载
- JAVA多线程下载的实现
- Android学习笔记---java实现多线程下载器,30_多线程下载原理介绍和使用
- 自学JAVA多线程下载
- 安卓学习之路 -- JAVA多线程下载
- Java / Android 基于Http的多线程下载的实现
- Java_java多线程下载-断点下载-超详细
- 【Java】:多线程下载
- Java / Android 基于Http的多线程下载的实现
- java 实现多线程下载(2)
- JAVA IO 之多线程下载
- JAVA 多线程下载
- Java--多线程下载,断点续传技术原理
- Android/Java多线程下载
- java多线程下载web上的资源数据
- Java多线程下载
- Java实现多线程下载及断点续传
- JAVA多线程下载,断点续传(HTTP)