断点续传和大文件下载

原创 2018年04月16日 22:09:26
实现原理
(1)首先获得下载文件的长度,然后设置本地文件的长度。
(2)根据文件长度和线程数计算每条线程下载的数据长度和下载位置。
如:文件的长度为6M,线程数为3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如下图所示:
?例如10M大小,使用3个线程来下载,
线程下载的数据长度 ? (10%3 == 0 ? 10/3:10/3+1) ,第1,2个线程下载长度是4M,第三个线程下载长度为2M
下载开始位置:线程id*每条线程下载的数据长度 = ?

下载结束位置:(线程id+1)*每条线程下载的数据长度-1=?

Activity代码
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    @SuppressLint("HandlerLeak")
    public static Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int size = msg.getData().getInt("size");
//            progressbar.setProgress();
            float temp = (float) size / (float)progressbar.getMax();
            int progress = (int) (temp * 100);
            if (progress == 100) {
                Log.e("TAG", "handleMessage: " + "下载完成");
            }
            tv_result.setText("下载进度:" + progress + "%");
        }
    };
    private EditText ed;
    private Button btn_download;
    private static ProgressBar progressbar;
    private static TextView tv_result;
    private String urlstring;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        ed = (EditText) findViewById(R.id.ed);
        btn_download = (Button) findViewById(R.id.btn_download);
        progressbar = (ProgressBar) findViewById(R.id.progressbar);
        tv_result = (TextView) findViewById(R.id.tv_result);


        btn_download.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_download:
                submit();
                download();
                break;
        }
    }

    //下载文件
    private void download() {
//获取sd卡路径
        String path = Environment.getExternalStorageDirectory() + "/morethreaddownload/";
        File file = new File(path);
        if (!file.exists()) {
//            如果文件目录不存在,就创建此文件夹
            file.mkdir();
        }


//      指定下载的大文件的名称
        String filename = "fulin.apk";
//        要下载的文件路径
        String filepath = path + filename;
//        线程的数量
        int threadcount = 5;


//  开启子线程下载文件(获取文件的长度)
        DownLoadTask task = new DownLoadTask(progressbar,urlstring,filepath,threadcount);
        task.start();
    }
    private void submit() {
//输入框中用户输入的网络路径
        urlstring = ed.getText().toString().trim();
        if (TextUtils.isEmpty(urlstring)) {
            Toast.makeText(this, "edString不能为空", Toast.LENGTH_SHORT).show();
            return;
        }
    }

}
DownLoadTask类
public class DownLoadTask extends Thread {
    //     网路文件的下载地址
    private String downloadUrl;
    //    保存文件的路径
    private String filePath;
    //    线程的数量
    private int threadcount;
//    进度条
    private ProgressBar  progressBar;
//    文件的大小
    public static int filesize;
    //    每个线程的下载量
    private int blockSize;
//构造方法
    public DownLoadTask(ProgressBar  progressBar, String downloadUrl, String filePath, int threadcount) {
        this.progressBar=progressBar;
        this.downloadUrl = downloadUrl;
        this.filePath = filePath;
        this.threadcount = threadcount;
    }

    @Override
    public void run() {
        super.run();
//        线程数组
        FileDownloadThread[] threads = new FileDownloadThread[threadcount];
        try {
            URL url = new URL(downloadUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.connect();
            if (conn.getResponseCode() == 200) {
//                读取下载文件的总长度
                filesize = conn.getContentLength();
                if (filesize <= 0) {
                    Log.e(TAG, "run: " + "读取文件失败");
                    return;
                }

//                设置progressbar的最大值
                progressBar.setMax(filesize);
//
//              计算每条线程下载的数据长度
                blockSize = filesize % threadcount == 0 ? filesize / threadcount : filesize / threadcount + 1;
//sd卡里边指定的保存网络端下载下来的文件
                File file = new File(filePath);
//                启动每个线程,分别下载所分配的长度
                for (int i = 0; i < threadcount; i++) {
                    threads[i] = new FileDownloadThread(file,url,(i+1),blockSize);
                    threads[i].setName("Thread:" + i);
                    threads[i].start();
                }
//是否下载完成
                boolean isfinished = false;
//                下载的总长度
                int downloadAllsize = 0;
                while (!isfinished) {
                    isfinished = true;
                    downloadAllsize = 0;
                    for (int i = 0; i < threadcount; i++) {
                        downloadAllsize += threads[i].getDownloadlenght();
                        if (!threads[i].isCompleted()) {
                            isfinished = false;
                        }
                    }
//                    通知handler去更新
                    Message message = new Message();
                    message.getData().putInt("size", downloadAllsize);
                    MainActivity.handler.sendMessage(message);
                    Thread.sleep(1000);
                }
                Log.e(TAG, "run:下载的总大小: "+ downloadAllsize);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class FileDownloadThread extends Thread {
    /**
     *  文件保存路径 
     */
    private File file;
    /**
     *  文件下载路径 (文件网址)
     */
    private URL downloadUrl;
    /**
     *  当前下载线程ID 
     */
    private int threadId;
    /**
     *  线程下载数据长度 
     */
    private int blockSize;
    private int downloadlenght;
    private boolean isCompleted;

    public FileDownloadThread(File file, URL downloadUrl, int threadId, int blockSize) {
        this.file = file;
        this.downloadUrl = downloadUrl;
        this.threadId = threadId;
        this.blockSize = blockSize;
    }


    @Override
    public void run() {
        super.run();
        BufferedInputStream  bis=null;

        RandomAccessFile raf=null;



        try {
            HttpURLConnection conn = (HttpURLConnection) downloadUrl.openConnection();
            conn.setAllowUserInteraction(true);
//         开始的位置
            int  startpos=blockSize*(threadId-1);
            int endpos=blockSize*threadId-1;
//            设置当前线程下载的开始点和结束点
            conn.setRequestProperty("Range","bytes="+startpos+"-"+endpos);
            byte[] buffer=new byte[1024];
            bis=new BufferedInputStream(conn.getInputStream());
            raf=new RandomAccessFile(file,"rwd");
            raf.seek(startpos);
            int len=0;
            while((len=bis.read(buffer,0,1024))!=-1){
                raf.write(buffer,0,len);
                downloadlenght+=len;
            }
            isCompleted=true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//每个线程下载的数据长度
    public int getDownloadlenght() {
        return downloadlenght;
    }
//返回线程是否下载完成
    public boolean isCompleted() {
        return isCompleted;
    }
}

FileDownloadThread类
class FileDownloadThread extends Thread {
    /**
     *  文件保存路径 
     */
    private File file;
    /**
     *  文件下载路径 (文件网址)
     */
    private URL downloadUrl;
    /**
     *  当前下载线程ID 
     */
    private int threadId;
    /**
     *  线程下载数据长度 
     */
    private int blockSize;
    private int downloadlenght;
    private boolean isCompleted;

    public FileDownloadThread(File file, URL downloadUrl, int threadId, int blockSize) {
        this.file = file;
        this.downloadUrl = downloadUrl;
        this.threadId = threadId;
        this.blockSize = blockSize;
    }


    @Override
    public void run() {
        super.run();
        BufferedInputStream  bis=null;

        RandomAccessFile raf=null;



        try {
            HttpURLConnection conn = (HttpURLConnection) downloadUrl.openConnection();
            conn.setAllowUserInteraction(true);
//         开始的位置
            int  startpos=blockSize*(threadId-1);
            int endpos=blockSize*threadId-1;
//            设置当前线程下载的开始点和结束点
            conn.setRequestProperty("Range","bytes="+startpos+"-"+endpos);
            byte[] buffer=new byte[1024];
            bis=new BufferedInputStream(conn.getInputStream());
            raf=new RandomAccessFile(file,"rwd");
            raf.seek(startpos);
            int len=0;
            while((len=bis.read(buffer,0,1024))!=-1){
                raf.write(buffer,0,len);
                downloadlenght+=len;
            }
            isCompleted=true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//每个线程下载的数据长度
    public int getDownloadlenght() {
        return downloadlenght;
    }
//返回线程是否下载完成
    public boolean isCompleted() {
        return isCompleted;
    }
}

实战COM(03)----创建一个进程外组件

 本文欢迎转载,唯请注明出处及作者 blackcolor@263.net---------------------------------------------------             ...
  • blackcolor
  • blackcolor
  • 2001-07-24 15:14:00
  • 1464

C#超大文件断点续传

  • 2017年08月01日 12:14
  • 9.96MB
  • 下载

大文件断点续传

最近项目较为清闲,研究了下Html5新增的几个重要技术点,如操作文件系统、获取摄像头麦克风、本地图片预览、Ajax上传文件等。灵光一现,我有了一个“墨迹”的想法:通过浏览器获取影音数据并实时存储到本地...
  • Netbug_NB
  • Netbug_NB
  • 2015-06-25 15:40:15
  • 1229

http大文件断点续传

  • 2013年09月15日 22:41
  • 294KB
  • 下载

大文件 and 多下载任务的封装(三)--断点续传,下载类的整合封装,以及使用

ThreadManager大文件 and 多下载任务的封装一 大文件 and 多下载任务的封装二 原文地址 上两篇文章中我们主要讲述了ThreadPool ,以及 Observer(观察者模式...
  • MyLoveyaqiong
  • MyLoveyaqiong
  • 2016-11-13 08:47:14
  • 1320

OKHttp实现大文件的断点续传

本文的亮点: (1)网络请求用OKHttp进行下载大文件 (2)实现了大文件的断点续传 (3)取消下载时,删除已经下载的文件。 实现效果图:          直接给出工程: (1)定义一个接口:D...
  • program_developer
  • program_developer
  • 2017-02-25 00:02:23
  • 4652

html5解决大文件断点续传

js代码 xhr2 将图片拖拽到此 0% ajax上传--> 上传 //拖拽上传开始 //-1.禁止浏览...
  • Zph1234
  • Zph1234
  • 2016-01-25 10:29:46
  • 6020

超大文件下载类 支持2g以上文件 支持断点续传

  • hjxisking
  • hjxisking
  • 2013-11-21 10:24:48
  • 854

基于Struts2大文件分片断点续传

话不多说,直接上代码。 1.java后台 package com.bjhit.eranges.actions.test; import java.io.BufferedReader; impo...
  • kerryzb
  • kerryzb
  • 2016-05-26 12:15:36
  • 1655

PHP 大文件下载,文件传输,支持断点续传。 2g以上超大文件也有效

  • u011976480
  • u011976480
  • 2014-01-27 22:17:02
  • 2574
收藏助手
不良信息举报
您举报文章:断点续传和大文件下载
举报原因:
原因补充:

(最多只允许输入30个字)