美文网首页
断点下载

断点下载

作者: 小慧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);
        }
    }
    
    

    相关文章

      网友评论

          本文标题:断点下载

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