美文网首页RxJava
RxJava<第三十三篇>:Retrofit2之上传

RxJava<第三十三篇>:Retrofit2之上传

作者: NoBugException | 来源:发表于2019-04-23 15:23 被阅读25次

    本文是RxJava<第三十二篇>:RxJava+Retrofit+OkHttp+MVP的扩展,着重分析单文件上传单文件下载

    本章重点想展示一下上传和下载的进度是如何实现的,后续会推出一个完整封装:RxJava+RxBinding+Retrofit+OkHttp+MVP+Dagger2来实现get请求、post请求、单文件上传、单文件下载、多文件上传、多文件下载

    (1)Retrofit+OkHttp实现文件上传

    第一步 自定义带进度条文件体

    /**
     * 带进度条的RequestBody封装
     */
    public class ProgressRequestBody extends RequestBody {
    
        private File mFile;
        private String mMediaType;//文件类型
        private UploadResultListener mListener;//上传结果回调监听
        private int bufferSize = 1024;//缓存大小
    
        public ProgressRequestBody(final File file, String mediaType, final UploadResultListener listener) {
            mFile = file;
            mMediaType = mediaType;
            mListener = listener;
        }
    
        public ProgressRequestBody(final File file, String mediaType, int eachBufferSize, final UploadResultListener listener) {
            mFile = file;
            mMediaType = mediaType;
            bufferSize = eachBufferSize;
            mListener = listener;
        }
    
        @Override
        public MediaType contentType() {
            return MediaType.parse(mMediaType);
        }
    
        @Override
        public void writeTo(BufferedSink sink) throws IOException {
            long fileLength = mFile.length();
            byte[] buffer = new byte[bufferSize];
            FileInputStream in = new FileInputStream(mFile);
            long uploaded = 0;
            try {
                int read;
                Handler handler = new Handler(Looper.getMainLooper());
                while ((read = in.read(buffer)) != -1) {
                    handler.post(new ProgressUpdate(uploaded, fileLength));
                    uploaded += read;
                    sink.write(buffer, 0, read);
                }
            } finally {
                in.close();
            }
        }
    
        private class ProgressUpdate implements Runnable {
            private long mUploaded;
            private long mTotal;
            public ProgressUpdate(long uploaded, long total) {
                mUploaded = uploaded;
                mTotal = total;
            }
    
            @Override public void run() {
                mListener.onProgressChange((int) (100 * mUploaded / mTotal));
            }
        }
    }
    

    第二步 上传文件结果回调监听

    /**
     * 上传文件监听接口
     */
    public interface UploadResultListener {
    
        void onProgressChange(int percent);//进度变化回调
        void onFinish();//上传完成回调
        void onInterrupted();//上传中断回调
    
    }
    

    第三步 retrofit接口定义

        public interface FileAPIService {
        
                //文件上传
                @Multipart
                @POST("FileUpload/FileUploadServlet")
                Call<ResponseBody> uploadFlie(@Part MultipartBody.Part file);
        
        
        }
    

    第四步 实现

        UploadResultListener uploadResultListener = new UploadResultListener() {
            @Override
            public void onProgressChange(int percent) {
                //进度条更新
                Log.d("aaa", "percent:"+percent + "%");
                ((TextView)findViewById(R.id.result_text1)).setText("当前上传进度:" + percent + "%");
            }
    
            @Override
            public void onFinish() {
                //上传完成
                ((TextView)findViewById(R.id.result_text1)).setText("上传完成");
            }
    
            @Override
            public void onInterrupted() {
                //上传中断
                ((TextView)findViewById(R.id.result_text1)).setText("上传失败");
            }
        };
    
        findViewById(R.id.bt_1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //单文件上传
    
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl("http://192.168.0.105:8080")
                        .build();
                FileAPIService fileAPIService = retrofit.create(FileAPIService.class);
    
                File file = new File(Environment.getExternalStorageDirectory() + File.separator + "myapk.apk");
    
                // 创建 RequestBody
                ProgressRequestBody progressRequestBody = new ProgressRequestBody(file, "application/otcet-stream", uploadResultListener);
    
                //新建Part
                MultipartBody.Part body = MultipartBody.Part.createFormData("myapk", file.getName(), progressRequestBody);
    
                Call<ResponseBody> call = fileAPIService.uploadFlie(body);
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        if(response != null && response.isSuccessful()){
                            uploadResultListener.onFinish();
                        }else{
                            uploadResultListener.onInterrupted();
                        }
                    }
    
                    @Override
                    public void onFailure(Call call, Throwable t) {
                        uploadResultListener.onInterrupted();
                    }
                });
    
            }
        });
    

    总体四步就可以实现文件的上传,其中第一步是带进度上传文件的核心。

    效果如下:


    图片.png 图片.png
    (2)Retrofit+OkHttp实现文件下载

    第一步 下载结果回调监听

    public interface DownloadResultListener {
    
        void onProgressChange(int percent);//进度变化回调
        void onFinish();//下载完成回调
        void onInterrupted();//下载中断回调
    
    }
    

    第二步 retrofit接口定义

    public interface FileAPIService {
    
    
        @Streaming
        @GET("/1.apk")
        Call<ResponseBody> downloadFile();
    }
    

    第三步 实现

        DownloadResultListener downloadResultListener = new DownloadResultListener() {
            @Override
            public void onProgressChange(int percent) {
                //进度条更新
                ((TextView)findViewById(R.id.result_text2)).setText("当前下载进度:" + percent+ "%");
            }
    
            @Override
            public void onFinish() {
                //上传完成
                ((TextView)findViewById(R.id.result_text2)).setText("下载完成");
            }
    
            @Override
            public void onInterrupted() {
                //上传中断
                ((TextView)findViewById(R.id.result_text2)).setText("下载失败");
            }
        };
    
        findViewById(R.id.bt_2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //文件下载
                Retrofit retrofit = new Retrofit.Builder().baseUrl("http://192.168.0.105:8080").build();
                FileAPIService searchFileAPIService = retrofit.create(FileAPIService.class);
                Call<ResponseBody> call = searchFileAPIService.downloadFile();
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        if(response != null && response.isSuccessful()){
                            new Thread(new Runnable() {
                                @Override
                                public void run() {
                                    boolean writtenToDisk = writeResponseBodyToDisk(response.body(), downloadResultListener);
                                    downloadResultListener.onFinish();
                                }
                            }).start();
    
                        }
                    }
    
                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                        downloadResultListener.onInterrupted();
                    }
                });
            }
        });
    
    //写入到磁盘根目录
    private boolean writeResponseBodyToDisk(ResponseBody body, DownloadResultListener downloadResultListener) {
        try {
            File futureStudioIconFile = new File(Environment.getExternalStorageDirectory() + File.separator + "mydownloadapk.apk");
            InputStream inputStream = null;
            OutputStream outputStream = null;
    
            try {
                byte[] fileReader = new byte[4096];
    
                int fileSize = (int) body.contentLength();
                int fileSizeDownloaded = 0;
    
                inputStream = body.byteStream();
                outputStream = new FileOutputStream(futureStudioIconFile);
                while (true) {
                    int read = inputStream.read(fileReader);
    
                    if (read == -1) {
                        break;
                    }
    
                    outputStream.write(fileReader, 0, read);
    
                    fileSizeDownloaded += read;
    
    
                    final int finalFileSizeDownloaded = fileSizeDownloaded;
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            downloadResultListener.onProgressChange(100 * finalFileSizeDownloaded / fileSize);
                        }
                    });
                }
    
                outputStream.flush();
    
                return true;
            } catch (IOException e) {
                return false;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
    
                if (outputStream != null) {
                    outputStream.close();
                }
            }
        } catch (IOException e) {
            return false;
        }
    }
    

    效果如下:

    图片.png 图片.png

    相关文章

      网友评论

        本文标题:RxJava<第三十三篇>:Retrofit2之上传

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