3多线程断点下载一个文件(android工程:java实现)

来源:互联网 发布:mem 知乎 编辑:程序博客网 时间:2024/06/05 20:58
import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.ProgressBar;import android.widget.TextView;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 {    //下载一个文件的线程数    public static int count = 3;    public static String basePath = "sdcard/";    //本地临时文件path    public static String localPath = basePath + "44.jpg";    //下载地址,你替换path的网址就行了    public static String path = "http://img.blog.csdn.net/20160130160136042?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center";    //the number of thread finished.    public static int currentFinished = 0;    //下载进度条    public ProgressBar pb;    //long是因为:如果下载了大文件,用int计算的时候就容易溢出    public long totalProgress = 0;    //下载进度显示,如%50    public TextView tv;    private Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            tv.setText("%" + (totalProgress * 100 / pb.getMax()));        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        pb = (ProgressBar) findViewById(R.id.pb);        tv = (TextView)findViewById(R.id.tv);    }    public void download(View view) {        new Thread(                new Runnable() {                    @Override                    public void run() {                        URL url;                        try {                            url = new URL(path);                            HttpURLConnection connection = (HttpURLConnection) url.openConnection();                            connection.setRequestMethod("GET");                            connection.setReadTimeout(5000);                            connection.setConnectTimeout(5000);                            if (connection.getResponseCode() == 200) {                                //拿到要下载文件的大小                                int length = connection.getContentLength();                                //指定临时文件的路径和文件名                                File file = new File(localPath);                                //创建随机文件存储对象                                RandomAccessFile raf = new RandomAccessFile(file, "rwd");                                //创建临时文件的大小,和服务器文件一模一样                                raf.setLength(length);                                //设置进度条的最大值                                pb.setMax(length);                                //计算每个线程下载的字节数                                int size = length / count;                                for (int i = 0; i < count; ++i) {                                    //计算3个线程下载数据的开始位置和结束位置                                    int startIndex = i * size;                                    int endIndex = (i + 1) * size - 1;                                    //如果是最后一个线程,name结束位置做特殊处理                                    if (i == count - 1) {                                        endIndex = length - 1;                                    }//                    System.out.println("线程" + i  + "的开始位置:" + startIndex//                            +"-------结束位置:" + endIndex);                                    new MyDownloadThread(i, startIndex, endIndex).start();                                }                            }                        } catch (Exception e) {                            e.printStackTrace();                        }                    }                }        ).start();    }    public static String getFileName(String path2) {        int index = path2.lastIndexOf("/");        return path2.substring(index + 1);    }    //下载类    class MyDownloadThread extends Thread {        int threadId;        int startIndex;        int endIndex;        public MyDownloadThread(int i, int startIndex, int endIndex) {            this.threadId = i;            this.startIndex = startIndex;            this.endIndex = endIndex;        }        @Override        public void run() {            try {                File fileProcess = new File(basePath + this.threadId + ".txt");                int currentPosition = this.startIndex;                if (fileProcess.exists()) {                    BufferedReader bufferedReader = new BufferedReader(                            new InputStreamReader(new FileInputStream(fileProcess)));                    int newStart = Integer.parseInt(bufferedReader.readLine());                    totalProgress = totalProgress + newStart - startIndex;                    this.startIndex = newStart;                    currentPosition = this.startIndex;                    bufferedReader.close();                    System.out.println("线程" + threadId + "的开始位置:" + startIndex                            + "-------结束位置:" + endIndex);                }                URL url = new URL(path);                HttpURLConnection connection = (HttpURLConnection) url.openConnection();                connection.setRequestMethod("GET");                connection.setReadTimeout(5000);                connection.setConnectTimeout(5000);                //设置请求数据的范围                connection.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);                //206说明请求的是部分数据,而200是请求的全部数据                if (connection.getResponseCode() == 206) {                    InputStream inputStream = connection.getInputStream();                    byte[] b = new byte[1024];                    //当前下载的总子节数                    int total = 0;                    int len = 0;                    //指定临时文件的路径和文件名                    File file = new File(localPath);                    RandomAccessFile raf = new RandomAccessFile(file, "rwd");                    //设置线程从哪个位置开始写入数据到临时文件                    raf.seek(startIndex);                    while ((len = inputStream.read(b)) != -1) {                        raf.write(b, 0, len);                        total += len;                        System.out.println("线程" + threadId + " 已经下载" + total);                        currentPosition = startIndex + total;                        RandomAccessFile rafProcessFile = new RandomAccessFile(fileProcess, "rwd");                        rafProcessFile.writeBytes(currentPosition + "");                        rafProcessFile.close();                        //下载进度更新                        totalProgress += len;                        pb.setProgress((int)totalProgress);                        handler.sendEmptyMessage(0);                    }                    raf.close();                    System.out.println("线程" + threadId + "下载完毕----------");                    currentFinished++;                    synchronized (MainActivity.class) {                        if (currentFinished == count) {                            for (int i = 0; i < count; ++i) {                                File tempFile = new File(basePath + i + ".txt");                                if (tempFile.exists()) {                                    tempFile.delete();                                }                            }                            currentFinished = 0;                        }                    }                }            } catch (Exception e) {                e.printStackTrace();            }        }    }}
  • activity.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <Button        android:text="下载"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:onClick="download" />    <ProgressBar        style="@android:style/Widget.ProgressBar.Horizontal"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:id="@+id/pb"/>    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/tv"        android:text="%0"/></LinearLayout>
  • 记得加权限
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>    <uses-permission android:name="android.permission.INTERNET"/>
0 0