资讯专栏INFORMATION COLUMN

Android多线程断点下载简单实现

ad6623 / 1338人阅读

摘要:多线程断点下载原理获取目标文件的大小在本地创建一个相同大小的文件并计算每个线程需要下载的起始位置及大小然后分配至每个线程独立下载全部下载完毕则自动合并实现步骤查看并计算目标文件的大小文件总长度为设置目标文件在本地的映射开启子线程并分配下载任

HTTP多线程断点下载

原理:获取目标文件的大小,在本地创建一个相同大小的文件,并计算每个线程需要下载的起始位置及大小,然后分配至每个线程独立下载,全部下载完毕则自动合并.

实现步骤

查看并计算目标文件的大小

URL url = new URL(mPath);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int code = connection.getResponseCode();
if (code == 200) {
    int length = connection.getContentLength();
    System.out.println("文件总长度为:" + length);

设置目标文件在本地的映射

RandomAccessFile raf = new RandomAccessFile(
        Environment.getExternalStorageDirectory().getAbsolutePath()
                +"/"+getDownlaodName(mPath), "rw");
raf.setLength(length);

开启子线程并分配下载任务

int blokeSize = length / mTotalCount;
System.out.println("每一块大小为:" + blokeSize);
runningThreadCount = mTotalCount;
for (int threadid = 0; threadid < mTotalCount; threadid++) {
    int startPosition = threadid * blokeSize;
    int endPosition = (threadid + 1) * blokeSize - 1;
    //最后一个线程应该下载至末尾
    if (threadid == mTotalCount - 1) {
        endPosition = length - 1;
    }
    System.out.println("线程编号:" + threadid + ""
            + ",下载范围:" + startPosition + "~~" + endPosition);
    //开启下载子线程
    new DownloadThread(threadid, startPosition, endPosition).start();

子线程中的具体逻辑

public void run() {
    System.out.println("线程"+threadid+"开始运行了");
    try{
        //读存有历史下载进度的文件,判断是否已经下载过
        File finfo=new File(Environment.getExternalStorageDirectory().getAbsolutePath()
                +"/"+mTotalCount + getDownlaodName(mPath)+threadid+".txt");
        if (finfo.exists()&&finfo.length()>0) {
            //获取文件输入流
            FileInputStream fis=new FileInputStream(finfo);
            //读取缓冲
            BufferedReader br=new BufferedReader(new InputStreamReader(fis));
            //得到文件内容
            String lasrposition=br.readLine();
            //转化为int值
            int intlastposition=Integer.parseInt(lasrposition);
            lastLoadSize=intlastposition-startPosition;
            startPosition=intlastposition;
            fis.close();
        }
        URL url=new URL(mPath);
        HttpURLConnection conn=(HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        System.out.println("线程实际下载:"+threadid+",范围:"+startPosition
                +"~~"+endPosition);
        //设置http请求头部参数
        conn.setRequestProperty("Range", "bytes="+startPosition+"-"+endPosition);
        int code=conn.getResponseCode();
        //206代表请求部分数据成功
        if (code==206) {
            //拿到链接返回的输入流
            InputStream is=conn.getInputStream();
            //指向要写的文件(abc.exe)
            RandomAccessFile raf=new RandomAccessFile(
                    Environment.getExternalStorageDirectory().getAbsolutePath()
                            +"/"+getDownlaodName(mPath), "rw");
            //指定文件开始写的位置
            raf.seek(startPosition);
            //下载缓冲区,越大下载越快,对硬盘损耗越小,但是越容易丢失数据
            byte[] buffer=new byte[1024*1024];
            int len=-1;
            int total=0;//当前线程本次下载数据总量
            while ((len=is.read(buffer))!=-1) {
                raf.write(buffer,0,len);
                total+=len;
                //将每次更新的数据同步到底层硬盘
                RandomAccessFile inforaf=new RandomAccessFile(
                        Environment.getExternalStorageDirectory().getAbsolutePath()
                        +"/"+mTotalCount +getDownlaodName(mPath)+threadid+".txt","rwd");
                //保存当前线程下载到什么位置
                inforaf.write(String.valueOf(startPosition+total).getBytes());
                inforaf.close();
            }
            is.close();
            raf.close();
            System.out.println("线程"+threadid+"下载完毕");

        }
    }catch(Exception e){
        e.printStackTrace();
    }finally{
        //同步代码块,保证同时间仅有一个线程执行此区块代码
        synchronized (MainActivity.class) {
            runningThreadCount--;
            if (runningThreadCount<=0) {
                System.out.println("多线程下载完毕");
                for (int i = 0; i 

备注:如果不使用断点下载,只需要将判断和存储历史下载信息的逻辑删除即可。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64908.html

相关文章

  • 线程系列之学习线程下载的基本原理和基本用法(1)

    摘要:多线程下载原理及步骤在本地创建一个大小跟服务器文件相同大小的临时文件。在这里在介绍一个有关多线程下载的中的相关类随机文件访问类只有才有搜寻方法,而这个方法也只适用于文件。利用这个类才能实现文件的多线程下载。 多线程下载在我们生活中非常常见,比如迅雷就是我们常用的多线程的下载工具,当然还有断点续传,断点续传我们在下一节来讲,android手机端下载文件时也可以用多线程下载,我们这里是在j...

    darry 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<