android之旅11 网络编程实例:多线程下载与断点续传

## 多线程下载其实哪里都在用,因此API都是JAVA的API,和Android关系不大 ##
- 请求文件长度
- 创建本地文件

String path = "www.baidu.com/xxx.jpg";
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
if(conn.getResponseCode()==200){
    int length = conn.getContentLength();
//  创建本地文件
    File file = new File("xxx.jpg");
    //随机读写,rw可读可写,d实时刷新内存数据到磁盘
    RandomAccessFile raf = new RandomAccessFile(file, "rwd");   
    raf.setLength(length);
    raf.close();
    //threadCount为自定义的多线程下载的线程数
    int size = length/threadCount;
    // 计算每个线程的起始结束下载位置
    for(int i=0; i<threadCount; i++){
        int startIdx = i*size;
        int endIdx = (i+1)*size-1;
        if (i==threadCount-1){
            endIdx = length-1; //可能除不尽
        }
    //启动线程开始下载,构造入参分别是线程ID,起始结束位置   
        new DownLoadThread(threadId, startIdx, endIdx).start();
    }
}
  • 线程下载
  • 断点续传
public DownLoadThread extends Thread{
    int startIdx;
    int endIdx;
    int threadId;
    /*构造函数.....*/

    public void run(){
        //断点续传,读取上次下载的结束位置
        File file = new File(ThreadIdx+".txt");
        if (file.exists()){
            FileInputStream fis = new FileInputStream(file);
            //存都是按照byte存储的,因此取出来要转为换char
            BufferedReader br = new BufferedReader(new InputStreamReader(fis));
            startIdx = Integer.parseInt(br.readLine());
            fis.close();
        }
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5000);
        conn.setReadTimeout(5000);
        conn.setRequestProperty("Range","bytes="+startIdx+"-"+endIdx);
        if (conn.getResponseCode()==206){//部分数据返回是206
            InputStream is = conn.getInputStream();
            bytes[] b = new bytes[1024];
            int len = 0;
            int total = startIdx;
            File file = new File("xxx.jpg");
            RandomAccessFile raf = newRandomAccessFile(file, "rwd");
            raf.seek(startIdx);//设置起始位置
            while((len=is.read(b))!=-1){
                raf.write(b, 0, len);
                total += len;
                File progressFile = newFile(threadId+".txt");
                RandomAccessFile praf = new RandomAccessFile(processFile, "rwd");//实时写入
                praf.write((total+"").getBytes());//每次都覆盖
                praf.close();//文件中数字可能差一个1024字节,临时文件一定要在raf.write后面
            }
            raf.close();

            //删除praf不能直接删除文件,可能存在一个线程完了其他线程没有结束,下次再次下载
            synchronized(){
                if (/*所有线程都ok*/){
                    //删除所有临时文件
                }
            }

        }

    }
}
  • 界面通过ProgressBar显示进度
  • 样式显示水平进度条
<ProgressBar
    android:id="@+id/pb"
    style="@android:style/Widget.ProgressBar.Horizontal"
/>
  • 设置ProcessBar的显示
//进图条最大值就是设置为源文件的长度
pb.setMax(conn.getContentLength());
//pb有特殊处理可以直接在子线程刷新UI

int progress;//设置个全局的进度字段,每个线程加上当前下载的长度
pb.setProcess(progress);//注意线程安全问题,synchronized

//断点续传时候,也要设置进度条,初始值也给进度条
//如果要显示数字进度,必须用long类型,不然会导致整形溢出
(long)pb.getProcess()*100/pb.getMax()+"%"

//数字进度(TextView)可能存在到99的情况,此时文件已经下完,强制刷新到100

xUtils

  • 很明显这个功能是通用方法
  • xUtils包含多线程断点续传
  • 工具依然在gitHub上
public void click(View v){
    HttpUtils utils = new HttpUtils();
    String url = "www.baidu.com/xxx.jpg"
    utils.download(url, "sdcard/xxx.jpg", true/*断点续传*/,true/*响应头返回文件名则重命名*/,new RequestCallBack<File>(){
        public void onSuccess(ResponseInfo<File> ri){
            //下载成功调用
        }
        public void onFailure(HttpException args, String reason){
            //下载失败调用,reason返回失败原因
        }

        public void onLoading(long total, long current, boolean isUploading){
            //中间刷新进度条什么的
        }
    });
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java多线程断点续传下载可以使用Java中的线程池和RandomAccessFile类实现。具体步骤如下: 1. 创建一个线程池,线程数量可以根据需要调整。 ``` ExecutorService executorService = Executors.newFixedThreadPool(threadCount); ``` 2. 获取文件大小和已经下载的字节数,计算出每个线程需要下载的字节数。 ``` URL url = new URL(fileUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); long fileSize = connection.getContentLength(); long threadSize = fileSize / threadCount; ``` 3. 创建一个RandomAccessFile对象,指定文件名和读写模式。 ``` RandomAccessFile randomAccessFile = new RandomAccessFile(fileName, "rw"); ``` 4. 为每个线程创建一个DownloadThread对象,指定线程编号、起始位置和结束位置。 ``` for (int i = 0; i < threadCount; i++) { long start = i * threadSize; long end = (i == threadCount - 1) ? fileSize - 1 : start + threadSize - 1; DownloadThread thread = new DownloadThread(fileUrl, randomAccessFile, start, end); executorService.execute(thread); } ``` 5. 在DownloadThread中使用HttpURLConnection下载文件,使用RandomAccessFile写入文件。 ``` URL url = new URL(fileUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestProperty("Range", "bytes=" + start + "-" + end); InputStream inputStream = connection.getInputStream(); byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) != -1) { randomAccessFile.write(buffer, 0, length); } inputStream.close(); ``` 6. 在程序关闭时,关闭RandomAccessFile和线程池。 ``` randomAccessFile.close(); executorService.shutdown(); ``` 这样就可以实现Java多线程断点续传下载了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值