Java多线程断点续传下载

来源:互联网 发布:简易c语言程序 编辑:程序博客网 时间:2024/05/01 16:36

提示:多线程环境下不能使用JUNIT进行测试,除非你能很好的控制,因为这个问题,浪费了很长时间。

/** * 多线程断点下载工具类 * @author Shmily */public class FileDownloadUtils {private static Logger logger = Logger.getLogger(FileDownloadUtils.class);  /** * 多线程文件下载 * @param path 文件下载路径 eg:/mnt/*.txt * @param storePath 文件的存储路径  eg:/mnt/sdcard/ * @param threadNumber 开启的线程数 * @return 是否下载成功 */public static boolean FileDownload(String path,String storePath,Integer threadNumber){//如果threadNumber为NULL,则默认为三个线程下载文件int localThreadNumber=(threadNumber==null)?3:threadNumber.intValue();URL downloadUrl=null;int fileSize=0;//下载的文件的大小int fileBlock=0;//每个线程下载的文件块大小try {downloadUrl=new URL(path);//打开链接HttpURLConnection coon= (HttpURLConnection)downloadUrl.openConnection();coon.setRequestMethod("GET");//请求最长延时时间60scoon.setReadTimeout(60*1000);int status=coon.getResponseCode();if(status==200){logger.info("网络响应成功");//获得网络响应的文件的大小fileSize=coon.getContentLength();//计算每个线程下载的文件块的大小fileBlock=fileSize/localThreadNumber;}else{logger.error("网络响应失败");}} catch (Exception e1) {logger.error("网络地址不存在");}RandomAccessFile tempFile=null;//在本地存储的文件try {File storeFile=new File(storePath+path.substring(path.lastIndexOf("/")+1));tempFile=new RandomAccessFile(storeFile, "rwd");tempFile.setLength(fileSize);//设置文件大小tempFile.close();//计算每个线程的起始下载位置for(int i=0;i<threadNumber;i++){int start=i*fileBlock;int end=0;if(i==(threadNumber-1)){end=fileSize;}else{end=(i+1)*fileBlock-1;}//创建新线程DownloadThread tempThread=new DownloadThread(i, start, end, path,storeFile);tempThread.start();logger.info("线程"+i+"开始下载文件,开始位置:"+start+"结束位置:"+end);}} catch (Exception e) {logger.error("创建本地存储文件失败");}return true;}}/** * 下载线程类 * @author Shmily */class DownloadThread extends Thread{private static Logger logger = Logger.getLogger(DownloadThread.class);  private int threadId;//线程IDprivate int start;//线程下载文件的数据起始位置private int end;//线程下载文件的数据结束位置private String path;//欲下载的文件的存储路径private File storeFile;//文件的存储路径public DownloadThread(int threadId, int start, int end,String path, File storeFile) {this.threadId = threadId;this.start = start;this.end = end;this.path = path;this.storeFile=storeFile;}@Overridepublic void run() {    Properties pro=StreamUtils.loadProperty("/com/zgs/stream/util/config.properties");//该线程下载的文件未下载完毕if(pro!=null&&pro.getProperty(threadId+"")!=null){logger.info("线程"+threadId+"从"+(String)pro.getProperty(threadId+"")+"继续下载");   String val=(String)pro.getProperty(threadId+"");   if(Integer.parseInt(val)>start)   //更新下载起始位置   start=Integer.parseInt(val);}try {URL downloadUrl = new URL(path);//打开链接HttpURLConnection coon= (HttpURLConnection)downloadUrl.openConnection();coon.setRequestMethod("GET");//请求最长延时时间5scoon.setReadTimeout(5000);coon.setRequestProperty("Range", "bytes="+start+"-"+ end);int status=coon.getResponseCode();logger.info("状态码:"+status);//多线程断点下载时服务器的响应的状态吗为206if(status==206||status==200){   //获得存储在本地的文件   RandomAccessFile tempFile=new RandomAccessFile(storeFile, "rwd");   //定位写文件的起始位置   tempFile.seek(start);   //打开服务器响应   InputStream in=coon.getInputStream();   //缓冲区   byte[] buffer=new byte[1024];   int len=0;   int currentLocation=start;//当前读取的文件位置   //读写数据   while((len=in.read(buffer))!=-1){   logger.info("线程"+threadId+"正在读取"+currentLocation);   tempFile.write(buffer,0,len);   currentLocation+=len;   //记录文件下一次开始下载的位置   StreamUtils.updateProperty("/com/zgs/stream/util/config.properties", threadId+"",currentLocation+"");   }   //移除对应的key   StreamUtils.updateProperty("/com/zgs/stream/util/config.properties", threadId+"");   tempFile.close();   logger.info("线程"+threadId+"下载完毕");}} catch (Exception e) {logger.error("网络连接异常");}}}



0 0