`
ry.china
  • 浏览: 139793 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

java断点下载

    博客分类:
  • java
阅读更多

忘了在哪里抄的这东西了,发上来由兴趣的可以去研究一下

 

 public class Task { 
  
  
  
   private String downURL; 
  
  
  
   private String saveFile; 
  
    
  
   private int bufferSize = 64 * 1024; 
  
    
  
   private int workerCount; 
  
    
  
   private int sectionCount; 
  
    
  
   private long contentLength; 
  
    
  
   private long[] sectionsOffset; 
  
    
  
   public static final int HEAD_SIZE = 4096; 
  
    
  
   //读下载描述文件内容 
  
   public synchronized void read(RandomAccessFile file) throws IOException { 
  
     byte[] temp = new byte[HEAD_SIZE]; 
  
     file.seek(0); 
  
     int readed = file.read(temp); 
  
     if (readed != temp.length) { 
  
       throw new RuntimeException(); 
  
     } 
  
     ByteArrayInputStream bais = new ByteArrayInputStream(temp); 
  
     DataInputStream dis = new DataInputStream(bais); 
  
     downURL = dis.readUTF(); 
  
     saveFile = dis.readUTF(); 
  
     sectionCount = dis.readInt(); 
  
     contentLength = dis.readLong(); 
  
      
  
     sectionsOffset = new long[sectionCount]; 
  
     for (int i = 0; i < sectionCount; i++) { 
  
       sectionsOffset[i] = file.readLong(); 
  
     } 
  
   } 
  
    
  
   //创建下载描述文件内容 
  
   public synchronized void create(RandomAccessFile file) throws IOException { 
  
     if (sectionCount != sectionsOffset.length) { 
  
       throw new RuntimeException(); 
  
     } 
  
     long len = HEAD_SIZE + 8 * sectionCount; 
  
     file.setLength(len); 
  
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
  
     DataOutputStream dos = new DataOutputStream(baos); 
  
     dos.writeUTF(downURL); 
  
     dos.writeUTF(saveFile); 
  
     dos.writeInt(sectionCount); 
  
     dos.writeLong(contentLength); 
  
     byte[] src = baos.toByteArray(); 
  
     byte[] temp = new byte[HEAD_SIZE]; 
  
     System.arraycopy(src, 0, temp, 0, src.length); 
  
     file.seek(0); 
  
     file.write(temp); 
  
     writeOffset(file); 
  
   } 
  
    
  
   //更新下载的过程 
  
   public synchronized void writeOffset(RandomAccessFile file) throws IOException { 
  
     if (sectionCount != sectionsOffset.length) { 
  
       throw new RuntimeException(); 
  
     } 
  
     file.seek(HEAD_SIZE); 
  
     for (int i = 0; i < sectionsOffset.length; i++) { 
  
       file.writeLong(sectionsOffset[i]); 
  
     } 
  
   } 
  
   (下面是Getter、Setter) 
  
 } 
  
  
  
 //这个是下载主程序 
  
  
  
 public class TaskAssign { 
  
  
  
   public void work(Task task) throws IOException { 
  
     File file = new File(task.getSaveFile()); 
  
     if (file.exists()) { 
  
       return; 
  
     } 
  
     //这个是记录是否下载成功。我这里也没有增加失败回复、重试之类的工作。 
  
     final AtomicBoolean success = new AtomicBoolean(true); 
  
     //任务描述文件 
  
     File taskFile = new File(task.getSaveFile() + ".r_task"); 
  
     //真正下载的文件 
  
     File saveFile = new File(task.getSaveFile() + ".r_save"); 
  
     boolean taskFileExist = taskFile.exists(); 
  
     RandomAccessFile taskRandomFile = null; 
  
     RandomAccessFile downRandomFile = null; 
  
     try { 
  
       taskRandomFile = new RandomAccessFile(taskFile, "rw"); 
  
       downRandomFile = new RandomAccessFile(saveFile, "rw"); 
  
       long rtnLen = getContentLength(task.getDownURL()); 
  
       if (!taskFileExist) { 
  
         //如果文件不存在,就初始化任务文件和下载文件 
  
         task.setContentLength(rtnLen); 
  
         initTaskFile(taskRandomFile, task); 
  
         downRandomFile.setLength(rtnLen); 
  
       } else { 
  
         //任务文件存在就读取任务文件 
  
         task.read(taskRandomFile); 
  
         if (task.getContentLength() != rtnLen) { 
  
           throw new RuntimeException(); 
  
         } 
  
       } 
  
       int secCount = task.getSectionCount(); 
  
       //分配线程去下载,这里用到线程池 
  
       ExecutorService es = Executors.newFixedThreadPool(task.getWorkerCount()); 
  
       for (int i = 0; i < secCount; i++) { 
  
         final int j = i; 
  
         final Task t = task; 
  
         final RandomAccessFile f1 = taskRandomFile; 
  
         final RandomAccessFile f2 = downRandomFile; 
  
         es.execute(new Runnable() { 
  
           public void run() { 
  
             try { 
  
               down(f1, f2, t, j); 
  
             } catch (IOException e) { 
  
               success.set(false); 
  
               e.printStackTrace(System.out); 
  
             } 
  
           } 
  
         }); 
  
       } 
  
       es.shutdown(); 
  
       try { 
  
         es.awaitTermination(24 * 3600, TimeUnit.SECONDS); 
  
       } catch (InterruptedException e) { 
  
         e.printStackTrace(); 
  
       } 
  
       taskRandomFile.close(); 
  
       taskRandomFile = null; 
  
       downRandomFile.close(); 
  
       downRandomFile = null; 
  
       //如果下载成功,去掉任务描述文件、帮下载文件改名 
  
       if (success.get()) { 
  
         taskFile.delete(); 
  
         saveFile.renameTo(file); 
  
       } 
  
     } finally { 
  
       if (taskRandomFile != null) { 
  
         taskRandomFile.close(); 
  
         taskRandomFile = null; 
  
       } 
  
       if (downRandomFile != null) { 
  
         downRandomFile.close(); 
  
         downRandomFile = null; 
  
       } 
  
     } 
  
   } 
  
    
  
   public void down(RandomAccessFile taskRandomFile, RandomAccessFile downRandomFile, Task task, int sectionNo) throws IOException { 
  
     //这里我用HttpURLConnection下载,你也可以用HttpClient或者自己实现一个Http协议(不过貌似没有必要) 
  
     URL u = new URL(task.getDownURL()); 
  
     HttpURLConnection conn = (HttpURLConnection) u.openConnection(); 
  
     long start = task.getSectionsOffset()[sectionNo]; 
  
     long end = -1; 
  
     //这里要注意一下,这里是计算当前块的长度 
  
     if (sectionNo < task.getSectionCount() - 1) { 
  
       long per = task.getContentLength() / task.getSectionCount(); 
  
       end = per * (sectionNo + 1); 
  
     } else { 
  
       end = task.getContentLength(); 
  
     } 
  
     if (start >= end) { 
  
       System.out.println("Section has finished before. " + sectionNo); 
  
       return; 
  
     } 
  
     String range = "bytes=" + start + "-" + (end - 1); 
  
     conn.setRequestProperty("Range", range); 
  
     conn.setRequestProperty("User-Agent", "Ray-Downer"); 
  
     try { 
  
       conn.connect(); 
  
       if (conn.getResponseCode() != 206) { 
  
         throw new RuntimeException(); 
  
       } 
  
       if (conn.getContentLength() != (end - start)) { 
  
         throw new RuntimeException(); 
  
       } 
  
       InputStream is = conn.getInputStream(); 
  
       byte[] temp = new byte[task.getBufferSize()]; 
  
       BufferedInputStream bis = new BufferedInputStream(is, temp.length); 
  
       int readed = 0; 
  
       while ((readed = bis.read(temp)) > 0) { 
  
         long offset = task.getSectionsOffset()[sectionNo]; 
  
         synchronized (task) { 
  
           //下载之后顺便更新描述文件,你可能会发现这里效率比较低,在一个线程同步里进行两次文件操作。你可以自己实现一个缓冲写。 
  
           downRandomFile.seek(offset); 
  
           downRandomFile.write(temp, 0, readed); 
  
           offset += readed; 
  
           task.getSectionsOffset()[sectionNo] = offset; 
  
           task.writeOffset(taskRandomFile); 
  
         } 
  
       } 
  
     } finally { 
  
       conn.disconnect(); 
  
     } 
  
     System.out.println("Section finished. " + sectionNo); 
  
   } 
  
    
  
   public void initTaskFile(RandomAccessFile taskRandomFile, Task task) throws IOException { 
  
     int secCount = task.getSectionCount(); 
  
     long per = task.getContentLength() / secCount; 
  
     long[] sectionsOffset = new long[secCount]; 
  
     for (int i = 0; i < secCount; i++) { 
  
       sectionsOffset[i] = per * i; 
  
     } 
  
     task.setSectionsOffset(sectionsOffset); 
  
     task.create(taskRandomFile); 
  
   } 
  
    
  
   public long getContentLength(String url) throws IOException { 
  
     URL u = new URL(url); 
  
     HttpURLConnection conn = (HttpURLConnection) u.openConnection(); 
  
     try { 
  
       return conn.getContentLength(); 
  
     } finally { 
  
       conn.disconnect(); 
  
     } 
  
   } 
  
 } 
  
  
  
 //稍微测试一下。 
  
 public class Main { 
  
    
  
   public static void main(String[] args) throws IOException { 
  
     test3(); 
  
     System.out.println("\n\n===============\nFinished."); 
  
   } 
  
   
  
   public static void test1() throws IOException { 
  
     Task task = new Task(); 
  
     task.setDownURL("http://61.152.235.21/qqfile/qq/2007iistable/QQ2007IIKB1.exe"); 
  
     task.setSaveFile("H:/Test2.exe"); 
  
     task.setSectionCount(200); 
  
     task.setWorkerCount(100); 
  
     task.setBufferSize(256 * 1024); 
  
     TaskAssign ta = new TaskAssign(); 
  
     ta.work(task); 
  
   } 
  
    
  
   public static void test2() throws IOException { 
  
     Task task = new Task(); 
  
     task.setDownURL("http://student1.scut.edu.cn:8880/manage/news/data/1208421861893.xls"); 
  
     task.setSaveFile("H:/Test3.xls"); 
  
     task.setSectionCount(5); 
  
     task.setWorkerCount(1); 
  
     task.setBufferSize(128 * 1024); 
  
     TaskAssign ta = new TaskAssign(); 
  
     ta.work(task); 
  
   } 
  
    
  
   public static void test3() throws IOException { 
  
     Task task = new Task(); 
  
     task.setDownURL("http://go.microsoft.com/fwlink/?linkid=57034"); 
  
     task.setSaveFile("H:/vc2005express.iso"); 
  
     task.setSectionCount(500); 
  
     task.setWorkerCount(200); 
  
     task.setBufferSize(128 * 1024); 
  
     TaskAssign ta = new TaskAssign(); 
  
     ta.work(task); 
  
   } 
  
    
  
   public static void test4() throws IOException { 
  
     Task task = new Task(); 
  
     task.setDownURL("http://down.sandai.net/Thunder5.7.9.472.exe"); 
  
     task.setSaveFile("H:/Thunder.exe"); 
  
     task.setSectionCount(30); 
  
     task.setWorkerCount(30); 
  
     task.setBufferSize(128 * 1024); 
  
     TaskAssign ta = new TaskAssign(); 
  
     ta.work(task); 
  
   } 
  
 }

  • 大小: 12.2 KB
分享到:
评论

相关推荐

    Java 实现的断点下载

    Java 断点下载技术是Java编程中用于网络文件下载的一种高效方法,特别是在处理大文件时,它允许用户中断和恢复...通过阅读和分析这个示例代码,你可以更深入地理解Java断点下载的实现机制,并将其应用于自己的项目中。

    java ftp断点上传和下载

    6. **开始断点续传下载**:使用`FTPClient`的`retrieveFile`方法,并传递本地文件和开始位置。 ```java OutputStream outputStream = new FileOutputStream(localFile); boolean success = ftpClient.retrieve...

    java 实现断点下载源码

    通过分析这个Java断点下载源码,我们可以深入理解网络编程中的文件下载策略,以及如何在Java中实现并发控制和状态管理,这对开发高效、稳定的网络应用非常有帮助。不过,实际应用中还需要考虑其他因素,比如服务器...

    Java网络编程多线程断点下载带界面选择文件夹进度条.zip

    在这个特定的项目中,我们关注的是一个实现多线程断点续传功能的Java应用程序,它还具有用户界面来选择保存文件的目录,并显示下载进度条。这个程序的实现涉及到以下几个关键知识点: 1. **Socket编程**:Java中的...

    多线程断点续传程序 java版本

    标题中的“多线程断点续传程序 Java版本”指的是一个使用Java编程语言实现的软件,该软件具备多线程下载功能,并且支持在下载中断后从上次停止的位置继续下载,即断点续传。这样的特性对于大文件下载或者网络环境不...

    Java断点续传

    Java 断点续传技术是网络传输中一种高效的数据...通过以上分析,我们可以看出Java断点续传涉及到了网络编程、文件操作、状态管理和错误处理等多个方面的知识,它在实际应用中能有效提高大文件传输的效率和用户体验。

    java断点续传

    Java断点续传技术在实际应用中广泛用于文件上传和下载工具,如迅雷、FTP客户端等,它有效地解决了大文件传输过程中的网络问题,提高了用户体验。了解并掌握这种技术对于开发高效的网络应用至关重要。

    java登录FTP下载文件,支持断点下载

    在Java编程环境中,FTP(File Transfer Protocol)文件下载是一个常见的任务,特别是在处理大量数据传输时。本场景中,我们关注的重点是如何实现一个功能完善的FTP下载工具,它支持断点续传,即当下载中断后可以从...

    java断点续传,刚刚整理出来多线程处理

    Java 断点续传技术是网络传输中常用的一种机制,特别是在大文件下载或上传时,如果因为网络中断或其他原因导致传输失败,可以借助断点续传功能从上次中断的地方继续,而无需重新开始。在Java中实现断点续传,通常...

    java 断点调试的各种方法

    Java 断点调试的各种方法 断点调试是 Java 程序员经常用的调试技术,通过设置断点,可以在代码运行到某一特定位置时停止,方便开发者检查和 debug 代码。下面将详细介绍 Java 断点调试的各种方法。 1. 条件断点 ...

    java断点续传Demo

    总之,Java断点续传技术是提高大文件下载效率的重要手段,通过HTTP的Range请求实现与服务器的交互,确保用户可以在任何时间点继续未完成的下载任务。在实际开发中,我们需要注意处理各种异常情况,以提供稳定可靠的...

    Java多线程断点下载Sample

    在这个“Java多线程断点下载Sample”示例中,我们将深入探讨如何利用Java的多线程特性来实现文件的断点续传下载,并结合进度条展示下载进度。 首先,我们需要理解什么是多线程。在单线程环境中,程序的执行顺序是...

    java 断点续传 多线程下载 线程池下载

    由于要写一个从第三方服务器...断点续传,多线程下载文件,idea开发工具需要安装 lombok 插件,具体百度下吧, 不过没有也没关系,我这里主要lombok 的set get、log 两个方法,具体自己可以重写 ,只为求分,git地址为...

    java断点续传源代码

    综上所述,Java断点续传技术涉及网络编程、文件操作和异常处理等多个方面,通过合理的实现可以显著提高大文件下载的效率和用户体验。理解并掌握这些知识点对于开发高效的文件下载应用至关重要。

    Java 多线程断点下载文件

    Java多线程断点下载文件是一种高效的文件下载方式,它允许在下载过程中暂停并从上次停止的地方继续,尤其适用于大文件下载。以下是实现这一功能的关键知识点: 1. **获取文件信息**: - 使用`java.net.URL`和`java...

    java 断点续传

    Java 断点续传技术是Java编程中一种重要的文件传输策略,主要用于大文件的上传和下载,能够提高网络效率并优化用户体验。在处理大文件时,由于网络不稳定、用户操作中断或其他因素,可能会导致文件传输失败。断点续...

    java 文件上传下载 断点续传 断点上传

    本文将详细介绍如何在Java中实现文件的上传与下载,并重点讨论断点续传和断点上传的技术实现。 首先,让我们从基础开始。在Web端进行文件上传通常涉及到HTML表单、Servlet或Spring MVC等技术。在HTML中,可以使用`...

    Java实现断点续传

    Java实现断点续传是一项在文件传输中非常实用的技术,特别是在大文件传输或者网络不稳定的情况下。断点续传允许用户在文件传输中断后从上次中断的位置继续,而不是重新开始整个传输过程,极大地提高了效率和用户体验...

Global site tag (gtag.js) - Google Analytics