zoukankan      html  css  js  c++  java
  • java 多线程断点下载功能

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.RandomAccessFile;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    
    public class Demo {
        
        //线程个数
        public static int threadCount = 3;
        
        //线程下载完成的个数
        public static int finishedCount = 3;
        /**
         * 多线程下载测试类
         * @param args
         * @throws Exception 
         */
        public static void main(String[] args) throws Exception {
            
            //1、连接服务器,获取一个文件,获取文件的长度,在本地创建一个大小跟服务器文件一样大的临时文件
            String path = "http://192.168.1.100:8080/test.avi";
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestMethod("GET");
            int code = conn.getResponseCode();
            if(code==200)
            {
                
                //服务器返回的数据长度 实际上就是文件的长度
                int length = conn.getContentLength();
                System.out.println("文件总长度:"+length);
                
                //在客服端创建出来一个大小跟服务器端文件一样大小的临时文件
                RandomAccessFile raf = new RandomAccessFile("test.avi", "rwd");
                //指定创建的这个文件的长度
                raf.setLength(length);
                raf.close();
                
                
                //假设是3个线程去下载资源
                //平均每一个线程下载的文件的大小
                int blockSize = length / threadCount;
                for(int threadId=1;threadId<=threadCount;threadId++)
                {
                    //线程下载的开始位置
                    int startIndex = (threadId-1)*blockSize;
                    int endIndex = threadId*blockSize;
                    if(threadId==threadCount)
                    {
                        endIndex = length;
                        
                    }
                    System.out.println("线程:"+threadId+" 下载:---"+startIndex+"--->"+endIndex);
                    
                    //启动线程
                    new DownloadThread(threadId,startIndex,endIndex,path).start();
                }
                
            }
            else
            {
                System.out.println("服务器错误");
            }
        
        
        }
        
        public static class DownloadThread extends Thread
        {
            private int threadId;  //线程id
            private int startIndex; 
            private int endIndex;
            private String path;
            
            public DownloadThread(int threadId, int startIndex, int endIndex,
                    String path) {
                super();
                this.threadId = threadId;
                this.startIndex = startIndex;
                this.endIndex = endIndex;
                this.path = path;
            }
    
            public void run() {
                try {
                    
                    //检查是否存在记录文件下载长度的文件,如果存在读取这个文件的数据
                    
                    File tempFile = new File(threadId+".txt");
                    if(tempFile.exists() && tempFile.length() >0)
                    {
                        FileInputStream fis = new FileInputStream(tempFile);
                        byte[] temp = new byte[1024];
                        int leng = fis.read(temp);
                        String downloadLen = new String(temp,0,leng);
                        int downloadLenInt = Integer.parseInt(downloadLen);
                        startIndex = downloadLenInt;
                        fis.close();
                    }
                    
                    System.out.println("线程:"+threadId+"实际下载:---"+startIndex+"--->"+endIndex);
                    
                    URL url = new URL(path);
                    HttpURLConnection conn =(HttpURLConnection) url.openConnection();
                    conn.setConnectTimeout(5000);
                    conn.setRequestMethod("GET");
                    
                    //重要 : 请求服务器下载部分的文件指定文件的位置
                    conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
                    
                    //从服务器请求全部资源 200 ok 如果从服务器请求部分资源 206 ok
                    int code = conn.getResponseCode();
                    System.out.println("code:"+code);
                    
                    //已经设置了请求的位置 返回的事当前位置对应的文件的输入流
                    InputStream is = conn.getInputStream();
                    
                    //在客服端创建出来一个大小跟服务器端文件一样大小的临时文件
                    RandomAccessFile raf = new RandomAccessFile("test.avi", "rwd");
                    //随机写文件的时候从哪个位置开始
                    raf.seek(startIndex); //定位文件
                    
                    int len = 0;
                    byte[] buffer = new byte[1024];
                    int total = 0;
                    while((len=is.read(buffer))!=-1)
                    {
                        //记录已经下载完成的长度
                        RandomAccessFile recordFile = new RandomAccessFile(threadId+".txt","rwd");
                        raf.write(buffer,0,len);
                        //下载完成的长度
                        total += len;
                        recordFile.write((total+startIndex +"").getBytes());
                        recordFile.close();
                        
                    }
                    
                    is.close();
                    raf.close();
                    
                    System.out.println("线程:"+threadId+"下载完毕了。。。");
                    
                } catch (Exception e) {
                    e.printStackTrace();
                }finally
                {
                    //用于删除各个线程记录已经下载完成的长度的文件
                    finishedCount--;
                    //所有线程下载完成
                    if(finishedCount==0)
                    {
                        
                        for(int i=1;i<=threadCount;i++)
                        {
                            //删除记录文件
                            File deleteFile = new File(i+".txt");
                            deleteFile.delete();
                        }
                        
                    }
                    
                }
            }
            
            
        }
    
    }
  • 相关阅读:
    【HTTP】长连接和短连接
    HTTP/1.1 持久连接 persistent connection
    浅谈Websocket、Ajax轮询和长轮询(long polling)
    web通信之跨文档通信 postMessage
    HTML5 postMessage 和 localStorage 实现窗口间通信
    CORS 和 JSONP
    【转】js中几种实用的跨域方法原理详解
    [跨域]前端解决跨域问题
    RFC1867 HTTP file upload
    Multipart/form-data POST文件上传
  • 原文地址:https://www.cnblogs.com/zoro-zero/p/3955015.html
Copyright © 2011-2022 走看看