• Java开发之多线程下载和断点续传


    代码实现了多线程下载和断点续传功能

      1 import java.io.BufferedReader;
      2 import java.io.File;
      3 import java.io.FileInputStream;
      4 import java.io.FileOutputStream;
      5 import java.io.IOException;
      6 import java.io.InputStream;
      7 import java.io.InputStreamReader;
      8 import java.io.RandomAccessFile;
      9 import java.net.HttpURLConnection;
     10 import java.net.URL;
     11 
     12 import javax.print.attribute.standard.Finishings;
     13 
     14 public class MultiDownload {
     15 
     16     static int ThreadCount = 3;
     17     static int finishedThread = 0;
     18     //确定下载地址
     19     static String path = "http://192.168.13.13:8080/QQPlayer.exe";
     20     public static void main(String[] args) {
     21         
     22         //发送get请求,请求这个地址的资源
     23         try {
     24             URL url = new URL(path);
     25             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
     26             conn.setRequestMethod("GET");
     27             conn.setConnectTimeout(5000);
     28             conn.setReadTimeout(5000);
     29             
     30             if(conn.getResponseCode() == 200){
     31                 //拿到所请求资源文件的长度
     32                 int length = conn.getContentLength();
     33                 
     34                 File file = new File("QQPlayer.exe");
     35                 //生成临时文件
     36                 RandomAccessFile raf = new RandomAccessFile(file, "rwd");
     37                 //设置临时文件的大小
     38                 raf.setLength(length);
     39                 raf.close();
     40                 //计算出每个线程应该下载多少字节
     41                 int size = length / ThreadCount;
     42                 
     43                 for (int i = 0; i < ThreadCount; i++) {
     44                     //计算线程下载的开始位置和结束位置
     45                     int startIndex = i * size;
     46                     int endIndex = (i + 1) * size - 1;
     47                     //如果是最后一个线程,那么结束位置写死
     48                     if(i == ThreadCount - 1){
     49                         endIndex = length - 1;
     50                     }
     51 //                    System.out.println("线程" + i + "的下载区间是:" + startIndex + "---" + endIndex);
     52                     new DownLoadThread(startIndex, endIndex, i).start();
     53                 }
     54             }
     55         } catch (Exception e) {
     56             // TODO Auto-generated catch block
     57             e.printStackTrace();
     58         }
     59     }
     60     
     61     
     62 }
     63 class DownLoadThread extends Thread{
     64     int startIndex;
     65     int endIndex;
     66     int threadId;
     67     
     68     public DownLoadThread(int startIndex, int endIndex, int threadId) {
     69         super();
     70         this.startIndex = startIndex;
     71         this.endIndex = endIndex;
     72         this.threadId = threadId;
     73     }
     74 
     75     @Override
     76     public void run() {
     77         //再次发送http请求,下载原文件
     78         try {
     79             File progressFile = new File(threadId + ".txt");
     80             //判断进度临时文件是否存在
     81             if(progressFile.exists()){
     82                 FileInputStream fis = new FileInputStream(progressFile);
     83                 BufferedReader br = new BufferedReader(new InputStreamReader(fis));
     84                 //从进度临时文件中读取出上一次下载的总进度,然后与原本的开始位置相加,得到新的开始位置
     85                 startIndex += Integer.parseInt(br.readLine());
     86                 fis.close();
     87             }
     88             System.out.println("线程" + threadId + "的下载区间是:" + startIndex + "---" + endIndex);
     89             HttpURLConnection conn;
     90             URL url = new URL(MultiDownload.path);
     91             conn = (HttpURLConnection) url.openConnection();
     92             conn.setRequestMethod("GET");
     93             conn.setConnectTimeout(5000);
     94             conn.setReadTimeout(5000);
     95             //设置本次http请求所请求的数据的区间
     96             conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
     97             
     98             //请求部分数据,相应码是206
     99             if(conn.getResponseCode() == 206){
    100                 //流里此时只有1/3原文件的数据
    101                 InputStream is = conn.getInputStream();
    102                 byte[] b = new byte[1024];
    103                 int len = 0;
    104                 int total = 0;
    105                 //拿到临时文件的输出流
    106                 File file = new File("QQPlayer.exe");
    107                 RandomAccessFile raf = new RandomAccessFile(file, "rwd");
    108                 //把文件的写入位置移动至startIndex
    109                 raf.seek(startIndex);
    110                 while((len = is.read(b)) != -1){
    111                     //每次读取流里数据之后,同步把数据写入临时文件
    112                     raf.write(b, 0, len);
    113                     total += len;
    114 //                    System.out.println("线程" + threadId + "下载了" + total);
    115                     
    116                     //生成一个专门用来记录下载进度的临时文件
    117                     RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd");
    118                     //每次读取流里数据之后,同步把当前线程下载的总进度写入进度临时文件中
    119                     progressRaf.write((total + "").getBytes());
    120                     progressRaf.close();
    121                 }
    122                 System.out.println("线程" + threadId + "下载完毕-------------------小志参上!");
    123                 raf.close();
    124                 
    125                 MultiDownload.finishedThread++;
    126                 synchronized (MultiDownload.path) {
    127                     if(MultiDownload.finishedThread == MultiDownload.ThreadCount){
    128                         for (int i = 0; i < MultiDownload.ThreadCount; i++) {
    129                             File f = new File(i + ".txt");
    130                             f.delete();
    131                         }
    132                         MultiDownload.finishedThread = 0;
    133                     }
    134                 }
    135                 
    136             }
    137         } catch (Exception e) {
    138             // TODO Auto-generated catch block
    139             e.printStackTrace();
    140         }
    141     }
    142 }
  • 相关阅读:
    两句话的区别在于目录的不同。
    关于系统的操作全在这里了。这个看起来很重要。
    屏幕坐标的方法
    改变轴心的操作。
    关于旋转的变换处理方法。
    对其位置
    点边同事移除的办法处理。
    移动的坐标变换
    判断文件是否存在的函数。
    把节点归零处理
  • 原文地址:https://www.cnblogs.com/liyiran/p/5062011.html
Copyright © 2020-2023  润新知