美文网首页
Http断点续传要点

Http断点续传要点

作者: SDY_0656 | 来源:发表于2017-09-26 16:41 被阅读0次

    在http断点续传的过程中,主要有以下几个方面要注意:
    1,新建一个temp文件,记录断点的位置,也就是上次下载的数量。
    2,采用RandomAccessFile来进行文件读写,RandomAccessFile相当于是一个文件输入输出流的结合。提供了一些在文件中操作位置的方法,比如定位用的getFilePointer( ),在文件里移动用的seek( ),以及判断文件大小的length( )、skipBytes()跳过多少字节数。

    断点续传的步骤主要是以下几点:
    1,判断temp文件是否存在,存在就读取进度,不存在就创建一个新的。
    2,将读取的进度写入请求头重,就是设置请求的范围,例如:
    HttpUrlConnection中是如下设置:
    conn.setRequestProperty("Range", "bytes=" + lastPostion + "-" + endposition);

    OKHttp设置在Header中:
    builder.addHeader("RANGE", "bytes=" + startIndex + "-" + (contentLength - 1));
    3,写入APK文件的时候,同时将进度写入temp文件。完成的时候删除temp文件,以及关闭RandomAccessFile。

    while ((len = is.read(buffer)) != -1) {
                        randomAccessFile.write(buffer, 0, len);//写入APK
                        downloadLength += len;
                        downloadInfo.setProgress(downloadLength);
                        cacheFile.seek(0);
                        cacheFile.write(String.valueOf(downloadLength).getBytes());  //记录进度
                    }
    

    下面是一个完整实例:

    public static class newThreadDown extends Thread {
        private String urlstr;
        private long lastPostion;
        private long endposition;
        public newThreadDown(String urlstr, long endposition) {
            this.urlstr = urlstr;
            this.endposition = endposition;
        }
    
        @Override
        public void run() {
            HttpURLConnection conn = null;
            try {
                URL url = new URL(urlstr);
                conn = (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(10 * 1000);
                conn.setRequestMethod("GET");
                conn.setReadTimeout(10 * 1000);
                long startposition = 0;
                // 创建记录缓存文件
                File tempfile = new File("e:\\" + 1 + ".txt");
                if (tempfile.exists()) {
                    InputStreamReader isr = new InputStreamReader(new FileInputStream(tempfile));
                    BufferedReader br = new BufferedReader(isr);
                    String lastStr = br.readLine();
                    lastPostion = Integer.parseInt(lastStr);
                    conn.setRequestProperty("Range", "bytes=" + lastPostion + "-" + endposition);
                    br.close();
                } else {
                    tempFile.createNewFile();
                    lastPostion = startposition;
                    conn.setRequestProperty("Range", "bytes=" + lastPostion + "-" + endposition);
                }
    
                if (conn.getResponseCode() == HttpURLConnection.HTTP_PARTIAL) {
                    System.out.println(206 + "请求成功");
                    InputStream is = conn.getInputStream();
                    RandomAccessFile accessFile = new RandomAccessFile(new File("e:\\" + path.substring(path.lastIndexOf("/") + 1)),
                            "rwd");
                    accessFile.seek(lastPostion);
                    randomAccessFile.seek(startIndex);
                    RandomAccessFile cacheFile = new RandomAccessFile(tempFile, "rwd");
                    System.out.println("开始位置" + lastPostion);
                    byte[] bt = new byte[1024 * 200];
                    int len = 0;
                    long total = 0;
                    while ((len = is.read(bt)) != -1) {
                        total += len;
                        accessFile.write(bt, 0, len);
                        long currentposition = startposition + total;
                        cacheFile.seek(0);
                        rf.write(String.valueOf(currentposition).getBytes());
                        rf.close();
                    }
                    System.out.println("下载完毕");
                    is.close();
                    accessFile.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            super.run();
        }
    }
    

    以上实现的是单线程下载,当要实现多线程下载的时候,做如下改进:
    1,对下载的文件进行分块,每个线程负责不同区块的下载,主要设置为设置下载的请求范围,设置文件的写入范围:

    conn.setRequestProperty("Range", "bytes=" + dEntity.startLocation + "-" + dEntity.endLocation);
    
    //创建可设置位置的文件
                    RandomAccessFile file = new RandomAccessFile(dEntity.tempFile, "rwd");
                    //设置每条线程写入文件的位置
                    file.seek(dEntity.startLocation);
    

    2,对每个线程的tempFile多加一个字段,判断该线程是否下载完,当所有线程都下载完的时候,才是整体下载完成。
    参考文章:http://www.jianshu.com/p/5b2e22c42467, 修正了原文中存在的BUG。

    相关文章

      网友评论

          本文标题:Http断点续传要点

          本文链接:https://www.haomeiwen.com/subject/cposextx.html