美文网首页
断点下载

断点下载

作者: 小慧sir | 来源:发表于2019-07-16 11:35 被阅读0次
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.Locale;
import java.util.concurrent.Executors;

import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.ByteString;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(this, MyService.class);
        startService(intent);
    }

    /**
     * OkHttp实现断点续传
     */
    public void downloadRange(View view) {
        view.setEnabled(false);
        Toast.makeText(this, "开始下载", Toast.LENGTH_SHORT).show();
        // downFromBreakPoint();
        Executors.newCachedThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    downMultipleThread();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 多线程下载
     */
    private void downMultipleThread() throws Exception {
        // 请求基本信息
        final String url = "https://alissl.ucdl.pp.uc.cn/fs08/2019/07/05/1/110_17e4089aa3a4b819b08069681a9de74b.apk";
        File directory = Environment.getExternalStorageDirectory();
        final File file = new File(directory, "a20190715.apk");
        // 通过HEAD请求获取文件大小
        final OkHttpClient client = new OkHttpClient();
        Request headRequest = new Request.Builder()
                .url(url)
                .head()
                .build();
        Call headerCall = client.newCall(headRequest);
        Response headResponse = headerCall.execute();
        long contentLength = headResponse.body().contentLength();
        System.out.println("contentLength " + contentLength);
        // 计算每个线程需要下载的范围
        int number = 3;
        long part = contentLength / number;
        for (int i = 0; i < number; i++) {
            final String key = "range" + i;
            SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);
            final long start = preferences.getLong(key, i * part);
            long end = (i + 1) * part - 1;
            if (i == (number - 1)) {
                end = contentLength;
            }
            System.out.println(start + " - " + end);
            final String range = String.format(Locale.CHINESE, "bytes=%d-%d", start, end);
            Executors.newCachedThreadPool().execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("开始:" + Thread.currentThread().getName());
                        Request request = new Request.Builder()
                                .url(url)
                                .header("range", range)
                                .get()
                                .build();
                        Call call = client.newCall(request);
                        cancelDelay(call, 2000);
                        Response response = call.execute();
                        RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
                        SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);
                        accessFile.seek(start);
                        InputStream inputStream = response.body().byteStream();
                        byte[] bytes = new byte[1024];
                        int len = inputStream.read(bytes);
                        while (len != -1) {
                            accessFile.write(bytes, 0, len);
                            preferences.edit().putLong(key, accessFile.getFilePointer()).apply();
                            len = inputStream.read(bytes);
                        }
                        System.out.println(response.body().contentLength());
                        System.out.println("结束:" + Thread.currentThread().getName());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    /**
     * 从断点处继续下载
     */
    private void downFromBreakPoint() {
        Executors.newCachedThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    downloadByOkHttp();
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println(e.getMessage());
                }
            }
        });
    }

    public void downloadByOkHttp() throws IOException {
        // 文件下载地址
        String url = "https://alissl.ucdl.pp.uc.cn/fs08/2019/07/05/1/110_17e4089aa3a4b819b08069681a9de74b.apk";
        // 创建下载文件对象
        File directory = Environment.getExternalStorageDirectory();
        File file = new File(directory, "20190715.apk");
        RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
        // 断点续传:重新开始下载的位置
        String range = String.format(Locale.CHINESE, "bytes=%d-", file.length());
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .header("range", range)
                .build();
        // 使用OkHttp请求服务器
        final Call call = client.newCall(request);
        Response response = call.execute();
        // cancelDelay(call,1000);
        // 连接服务器成功
        ResponseBody body = response.body();
        System.out.println("文件大小:" + body.contentLength());
        String header = response.header("Content-Range");
        System.out.println(header);
        // 移动文件指针到断点续传的位置
        accessFile.seek(file.length());
        // 开始断点续传
        InputStream inputStream = body.byteStream();
        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);
        while (len != -1) {
            accessFile.write(bytes, 0, len);
            System.out.println("已下载字节:" + file.length());
            len = inputStream.read(bytes);
        }
        System.out.println("文件下载完毕:" + accessFile.getFilePointer());
    }

    public void cancelDelay(final Call call, long delayMillis) {
        Handler handler = new Handler(Looper.getMainLooper());
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                call.cancel();
            }
        }, delayMillis);
    }
}

相关文章

  • 基于Okhttp实现断点下载(续传)和分片下载

    断点下载/续传 断点下载是针对下载大文件需求的一种优化机制,可以从上次下载的断点处继续下载。断点续传原理也相同,只...

  • 断点下载

    效果图 断点下载的过程 这里是简单的一个下载,下一篇介绍列表的断点下载1.绘制UI图,并初始化控件2.创建实体类:...

  • 断点下载

    今天做了断点下载视频或者MP3,具体实现如下 1、主要应用了NSURLSessionDownloadTask和NS...

  • 断点下载

    链接转载;判断当前Service是否是重启的Servciehttp://blog.csdn.net/luyi325...

  • 断点下载

    http://www.jianshu.com/p/f65e32012f07

  • 断点下载

    断点下载重点 利用HTTP请求头的Range属性,就可以实现从指定位置开始下载表示头500个字节:Range: b...

  • 断点下载

    需要遵循NSURLConnectionDataDelegate协议/** 当前的长度/@property (no...

  • 断点下载

  • OC网络:NSURLSession-downloadTask的断

    NSURLSessionDownloadDelegate断点下载说明: 能实现断点下载,即在程序不退出的情况下:暂...

  • Android下载文件(一)下载进度&断点续传

    索引 Android下载文件(一)下载进度&断点续传 Android下载文件(二)多线程并发&断点续传(待续) A...

网友评论

      本文标题:断点下载

      本文链接:https://www.haomeiwen.com/subject/zkpzkctx.html