简单的多线程下载和断点续传

1.先要计算出资源文件的长度,根据长度随机创建一个文件,把文件请求分段

2.计算出线程下载的开始和结束位置

3.建立一个文件记录当前的下载的进度文件

4.下载完成后,删除记录的文件

权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">uses-permission>
布局

xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.lenovo.duoxianchengdemo.MainActivity">


    <Button
        android:text="Button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_marginRight="115dp"
        android:layout_marginEnd="115dp"
        android:layout_marginTop="180dp"
        android:onClick="start" />

    <ProgressBar
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="82dp"
        android:id="@+id/pb" />
RelativeLayout>

package com.example.lenovo.duoxianchengdemo;

import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ProgressBar;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends AppCompatActivity {
    //确定地址
//    static  String path="https://github.com/Bilibili/DanmakuFlameMaster.git";
    String Name="EditPlus.exe";
    String path="http://169.254.203.92:8080/zhbj/"+Name;
    static  int ThreadCount=3;
    static int ProgressCount=0;
    private HttpURLConnection conn;
    private ProgressBar pb;
    private int CurrentProgress=0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pb = (ProgressBar) findViewById(R.id.pb);

    }
    public void start(View v){
        new Thread(new Runnable() {
            @Override
            public void run() {
                //发送get请求
                try {
                    URL url=new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(5000);
                    conn.setReadTimeout(5000);
                    if(conn.getResponseCode()==200){
                        //拿到资源文件的长度
                        int  length = conn.getContentLength();
                        //设置progress的总长度
                        pb.setMax(length);
                        File file=new File(Environment.getExternalStorageDirectory(),"aa.txt");
                        //生成临时文件
                        RandomAccessFile raf=new RandomAccessFile(file,"rwd");
                        //设置临时文件的大小
                        raf.setLength(length);
                        //关闭
                        raf.close();
                        //计算出线程下载的字节
                        int size=length/ ThreadCount;
                        for (int i = 0; i <ThreadCount ; i++) {
                            //计算线程下载的开始位置和结束位置
                            int startIndex=i*size;
                            int endIndex=(i+1)*size-1;
                            //如果是最后一个线程,那么结束位置写死
                            if(i==ThreadCount-1){
                                endIndex=length-1;
                            }
                            System.out.println(endIndex+""+startIndex+""+endIndex);
                            new DownLoadThread(startIndex,endIndex,i).start();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
    class DownLoadThread extends Thread{
        int startIndex;
        int endIndex;
        int countId;
        int total;
        public DownLoadThread(int startIndex,int endIndex,int countId){
            this.startIndex=startIndex;
            this.endIndex=endIndex;
            this.countId=countId;
        }
        @Override
        public void run() {
            super.run();
            //再次发送网络请求,下载原文件
            try {
                File progressFile=new File(Environment.getExternalStorageDirectory(),countId+".txt");
                //判断临时文件是否存在
                if(progressFile.exists()){
                    FileInputStream fis=new FileInputStream(progressFile);
                    BufferedReader br=new BufferedReader(new InputStreamReader(fis));
                    //修改开始位置
//                    br.readLine();  读取临时文件的记录下载位置,使得断点续传能够启动
                    
int pro=Integer.parseInt(br.readLine());
CurrentProgress+=pro;
//让progress能够记录当前的进度,然后可以进行断点续传的时候重新显示
pb.setProgress(CurrentProgress);
startIndex+=pro;
}
URL url= new URL( path);
 HttpURLConnection conn= (HttpURLConnection) url.openConnection();
conn.setRequestMethod( "GET");
conn.setConnectTimeout( 5000);
conn.setReadTimeout( 5000); //设置本次http请求的数据区间 conn.setRequestProperty( "Range", "bytes="+ startIndex+ "-"+ endIndex); //请求部分数据是206 if(conn.getResponseCode()== 206){ //获取文件输入流 InputStream is=conn.getInputStream(); byte [] b= new byte[ 1024]; int len= 0; //拿到临时文件的引用 File file= new File(Environment. getExternalStorageDirectory(), Name); //生成临时文件 RandomAccessFile raf= new RandomAccessFile(file, "rwd"); //把文件的写入位置移动到startIndex,避免文件下载的覆盖 raf.seek( startIndex); while((len=is.read(b))!=- 1){ //读取流中的数据,写入到临时文件中 total+=len; raf.write(b, 0,len); System. out.println( "线程"+ countId+ "下载了"+ total); CurrentProgress+=len; //设置progress的当前进度 pb本身就是属于耗时的操作,允许在子线程中更新ui pb.setProgress( CurrentProgress); //生成一个专门的文件记录下载进度的临时文件 用于断点续传的记录 RandomAccessFile progressRaf= new RandomAccessFile(progressFile, "rwd"); progressRaf.write(( total+ "").getBytes()); progressRaf.close(); } System. out.println( "线程"+ countId+ "下载完毕!"); raf.close(); //下载完毕后删除下载的临时文件 ProgressCount++; //为了避免线程的不安全,直接开设同步代码块 //参数是唯一的值都可以 synchronized ( path){ if( ProgressCount== ThreadCount){ for( int i= 0;i< ThreadCount;i++){ File f= new File(i+ ".txt"); f.delete(); } ProgressCount= 0; } } } } catch (Exception e) { e.printStackTrace(); } } }}
 
  

你可能感兴趣的:(简单的多线程下载和断点续传)