• Android 开发 框架系列 OkHttp文件下载功能实现(含断点续传)


    前言

      此篇博客只是下载功能的记录demo,如果你还不太了解okhttp可以参考我的另一篇博客 https://www.cnblogs.com/guanxinjing/p/9708575.html

    代码部分

    package okhttpdemo.com.libs.net.httpBase;
    import android.util.Log;
    import org.json.JSONObject;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.RandomAccessFile;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    import okhttp3.Call;
    import okhttp3.Callback;
    import okhttp3.FormBody;
    import okhttp3.MediaType;
    import okhttp3.OkHttpClient;
    import okhttp3.Request;
    import okhttp3.RequestBody;
    import okhttp3.Response;
    import okhttp3.ResponseBody;
    import okhttpdemo.com.libs.net.httpBase.listener.HttpDownListener;
    /**
     *@content: okhttp的下载功能工具类 (分别包含:1.无断点续传的get下载 2.有断点续传的get下载 3.无断点续传的post下载 4.有断点续传的post下载)
     *@time:2018-12-12
     *@build:z
     */
    
    public class OkHttpDownUtil {
        private static final String TAG = "OkHttpDownUtil";
        private Call mCall;
        private long mAlreadyDownLength = 0;//已经下载长度
        private long mTotalLength = 0;//整体文件大小
        private int mSign = 0; //标记当前运行的是那个方法
        private String mDownUrl;//下载网络地址
        private File mPath;//文件保存路径
        private JSONObject mJson;
        private HttpDownListener mHttpDownListener;//下载进度接口回调
    
    
        /**
         * 没有断点续传功能的get请求下载
         * @param downUrl 下载网络地址
         * @param saveFilePathAndName 保存路径
         */
        public void getDownRequest(final String downUrl, final File saveFilePathAndName, final HttpDownListener listener) {
            mSign = 1;
            mDownUrl = downUrl;
            mPath = saveFilePathAndName;
            mHttpDownListener = listener;
            mAlreadyDownLength = 0;
            Request request = new Request.Builder()
                    .url(mDownUrl)
                    .get()
                    .build();
            mCall = OkHttpClientCreate.CreateClient().newCall(request);//构建了一个完整的http请求
            mCall.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    if (mHttpDownListener != null) {
                        mHttpDownListener.onFailure(call, e);
                    }
    
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    ResponseBody responseBody = response.body();
                    mTotalLength = responseBody.contentLength();//下载文件的总长度
                    InputStream inp = responseBody.byteStream();
                    FileOutputStream fileOutputStream = new FileOutputStream(mPath);
                    try {
                        byte[] bytes = new byte[2048];
                        int len = 0;
                        while ((len = inp.read(bytes)) != -1) {
                            mAlreadyDownLength = mAlreadyDownLength + len;
                            fileOutputStream.write(bytes, 0, len);
                            if (mHttpDownListener != null) {
                                mHttpDownListener.onResponse(call, response, mTotalLength, mAlreadyDownLength);
                            }
    
                        }
                    } catch (Exception e) {
                        Log.e(TAG, "Get下载异常");
    
                    } finally {
                        fileOutputStream.close();
                        inp.close();
                        Log.e(TAG, "流关闭");
                    }
                }
            });
        }
    
        /**
         * 有断点续传功能的get下载
         * @param downUrl 下载地址
         * @param saveFilePathAndName 保存路径
         * @param listener 进度监听
         */
        public void getRenewalDownRequest(final String downUrl, final File saveFilePathAndName, final HttpDownListener listener){
                mSign = 2;
                mDownUrl = downUrl;
                mPath = saveFilePathAndName;
                mHttpDownListener = listener;
                Request request = new Request.Builder()
                        .url(mDownUrl)
                        .header("RANGE", "bytes=" + mAlreadyDownLength + "-")
                        .build();
                mCall = OkHttpClientCreate.CreateClient().newCall(request);//构建了一个完整的http请求
                mCall.enqueue(new Callback() { //发送请求
                    @Override
                    public void onFailure(Call call, IOException e) {
                        if (mHttpDownListener != null) {
                            mHttpDownListener.onFailure(call, e);
                        }
                        Log.e(TAG, "onFailure: 异常报错=" + e.toString());
    
                    }
    
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        ResponseBody responseBody = response.body();
                        InputStream inputStream = responseBody.byteStream();//得到输入流
                        RandomAccessFile randomAccessFile = new RandomAccessFile(mPath, "rw");//得到任意保存文件处理类实例
                        if (mTotalLength == 0){
                            mTotalLength = responseBody.contentLength();//得到文件的总字节大小
                            randomAccessFile.setLength(mTotalLength);//预设创建一个总字节的占位文件
                        }
                        if (mAlreadyDownLength != 0){
                            randomAccessFile.seek(mAlreadyDownLength);
                        }
                        byte[] bytes = new byte[2048];
                        int len = 0;
                        try {
                            while ((len = inputStream.read(bytes)) != -1) {
                                randomAccessFile.write(bytes,0,len);
                                mAlreadyDownLength = mAlreadyDownLength + len;
                                if (mHttpDownListener != null) {
                                    mHttpDownListener.onResponse(call, response, mTotalLength, mAlreadyDownLength);
                                }
                            }
    
                        } catch (Exception e) {
                            Log.e(TAG, "Get下载异常");
    
                        } finally {
                            mAlreadyDownLength = randomAccessFile.getFilePointer();//记录当前保存文件的位置
                            randomAccessFile.close();
                            inputStream.close();
                            Log.e(TAG, "流关闭 下载的位置="+mAlreadyDownLength);
                        }
    
                    }
                });
        }
    
        /**
         * 没有断点续传的post下载
         * @param downUrl
         * @param saveFilePathAndName
         * @param json
         * @param listener
         */
        public void postDownRequest(final String downUrl, final File saveFilePathAndName, final JSONObject json,final HttpDownListener listener){
               mSign = 3;
               mDownUrl = downUrl;
               mPath = saveFilePathAndName;
               mJson = json;
               mHttpDownListener = listener;
               mAlreadyDownLength = 0;
               Request request = new Request.Builder()
                       .url(mDownUrl)
                       .post(changeJSON(json))
                       .build();
               mCall = OkHttpClientCreate.CreateClient().newCall(request);
               mCall.enqueue(new Callback() {
                   @Override
                   public void onFailure(Call call, IOException e) {
                       if (mHttpDownListener!=null){
                           mHttpDownListener.onFailure(call,e);
                       }
                   }
    
                   @Override
                   public void onResponse(Call call, Response response) throws IOException {
    
                       ResponseBody responseBody = response.body();
                       mTotalLength = responseBody.contentLength();
                       InputStream inputStream = responseBody.byteStream();
                       FileOutputStream fileOutputStream = new FileOutputStream(mPath);
                       byte[] bytes = new byte[2048];
                       int len = 0;
                       try {
                           while ((len = inputStream.read(bytes)) != -1) {
                               fileOutputStream.write(bytes, 0, len);
                               mAlreadyDownLength = mAlreadyDownLength + len;
                               if (mHttpDownListener != null) {
                                   mHttpDownListener.onResponse(call, response, mTotalLength, mAlreadyDownLength);
                               }
                           }
                       }catch (Exception e){
                           Log.e(TAG, "Post下载异常");
                       }finally {
                           fileOutputStream.close();
                           inputStream.close();
                           Log.e(TAG, "流关闭");
    
                       }
    
                   }
    
               });
    
        }
    
        /**
         * 支持断点续传的post下载
         * @param downUrl 下载网址
         * @param saveFilePathAndName 文件保存路径
         * @param json 参数
         * @param listener 接口回调
         */
        public void postRenewalDownRequest(final String downUrl, final File saveFilePathAndName, final JSONObject json, final HttpDownListener listener){
                mSign = 4;
                mDownUrl = downUrl;
                mPath = saveFilePathAndName;
                mJson = json;
                mHttpDownListener = listener;
                Request request = new Request.Builder()
                        .url(mDownUrl)
                        .header("RANGE","bytes="+mAlreadyDownLength+"-")
                        .post(changeJSON(json))
                        .build();
                mCall = OkHttpClientCreate.CreateClient().newCall(request);
                mCall.enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        if (mHttpDownListener != null){
                            mHttpDownListener.onFailure(call,e);
                        }
                    }
    
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        ResponseBody responseBody = response.body();
                        InputStream inputStream = responseBody.byteStream();
                        RandomAccessFile randomAccessFile = new RandomAccessFile(mPath,"rw");
                        if (mTotalLength == 0){
                            mTotalLength = responseBody.contentLength();
                            randomAccessFile.setLength(mTotalLength);
                        }
                        if (mAlreadyDownLength!=0){
                            randomAccessFile.seek(mAlreadyDownLength);
                        }
                        byte[] bytes = new byte[2048];
                        int len = 0;
                        try {
                            while ((len = inputStream.read(bytes)) != -1) {
                                randomAccessFile.write(bytes, 0, len);
                                mAlreadyDownLength = mAlreadyDownLength + len;
                                if (mHttpDownListener != null) {
                                    mHttpDownListener.onResponse(call, response, mTotalLength, mAlreadyDownLength);
                                }
    
                            }
                        }catch (Exception e){
                            Log.e(TAG, "Post下载异常");
    
                        }finally {
                            mAlreadyDownLength = randomAccessFile.getFilePointer();
                            randomAccessFile.close();
                            inputStream.close();
                            Log.e(TAG, "流关闭 下载的位置="+mAlreadyDownLength);
                        }
    
                    }
                });
        }
    
        /**
         * 恢复下载
         */
        public void resume(){
            if (mSign==0){
                return;
            }
            switch (mSign){
                case 1:
                    getDownRequest(mDownUrl,mPath,mHttpDownListener);
                    break;
                case 2:
                    getRenewalDownRequest(mDownUrl,mPath,mHttpDownListener);
                    break;
                case 3:
                    postDownRequest(mDownUrl,mPath,mJson,mHttpDownListener);
                    break;
                case 4:
                    postRenewalDownRequest(mDownUrl,mPath,mJson,mHttpDownListener);
                    break;
                default:
                    break;
            }
    
        }
    
        /**
         * 暂停下载
         */
        public void stop(){
            if (mCall!=null){
                mCall.cancel();
            }
    
        }
    
        /**
         * 删除下载文件
         */
        public void deleteCurrentFile(){
            if (mPath == null){
                Log.e(TAG, "deleteCurrentFile error : 没有路径");
                return;
            }
            if (!mPath.exists()){
                Log.e(TAG, "deleteCurrentFile error: 文件不存在");
                return;
            }
            mPath.delete();
            mAlreadyDownLength = 0;
            mTotalLength = 0;
            mSign = 0;
        }
    
        /**
         * 销毁
         */
        public void destroy(){
            if (mCall!=null){
                mCall.cancel();
                mCall = null;
            }
            mSign = 0;
            mDownUrl = null;
            mPath = null;
            mHttpDownListener = null;
            mAlreadyDownLength = 0;
            mTotalLength = 0;
        }
    
        /**
         * 转换Json参数为RequestBody
         * @param jsonParam json对象
         * @return RequestBody
         */
        private RequestBody changeJSON(JSONObject jsonParam){
            RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8")
                    , String.valueOf(jsonParam));
            return requestBody;
        }
    
    }
  • 相关阅读:
    Atitit 查找算法 艾提拉大总结 目录 1. 查找算法分类 1 1.1. 简单查找算法之折半查找、插值查找、斐波那契查找 1 1.2. 按照数据结构查找法分类 hash 表 1 2. 第8章查找
    Atitit 数据结构与常见文件元数据结构 目录 1. 分类 内部数据结构与外部存储数据结构 1 2. 编程语言内部数据结构 (堆栈 树 图等 1 2.1. 数据结构 (集合,列表,tree,map
    关于“王福朋详解petshop4.0系列视频教程”的开放下载问题
    《王福朋petshop4.0视频教程》新浪视频地址
    《petshop4.0视频教程》在线看
    《微软petshop4.0视频教程》 开放下载了!!!
    看马克扎克伯格创建facebook——电影《社交网络》观后感
    《王福朋petshop4.0视频教程》新浪视频(高清)
    当ListView控件在后台绑定数据源时,用DataPager控件分页需要注意的问题
    《王福朋petshop4.0视频教程》下载通知
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/11522472.html
Copyright © 2020-2023  润新知