首页 > 系统 > Android > 正文

RxJava+Retrofit+OkHttp实现文件上传

2019-10-22 18:23:00
字体:
来源:转载
供稿:网友

背景

在实际运用中上传是一个必不可少的功能,所以我们在封装二的基础上加入上传的功能,同时需要附带上传进度!

效果

RxJava,Retrofit,OkHttp文件上传

实现

1.定义service接口

注意:Multipart是指定大文件上传过程中的标示,一般上传图片的过程中我们需要附带信息,所以我们需要用到@part指定传递的数值,MultipartBody.Part是指定传递的文件;

  /*上传文件*/  @Multipart  @POST("AppYuFaKu/uploadHeadImg")  Observable<BaseResultEntity<UploadResulte>> uploadImage(@Part("uid") RequestBody uid, @Part("auth_key") RequestBody auth_key,@Part MultipartBody.Part file);

2.加入进度条

retrofit是基于okhttp的处理,所以我们可以自定义RequestBody,复写writeTo(BufferedSink sink)方法,得到传递的进度数据

public class ProgressRequestBody extends RequestBody {  //实际的待包装请求体  private final RequestBody requestBody;  //进度回调接口  private final UploadProgressListener progressListener;  //包装完成的BufferedSink  private BufferedSink bufferedSink;  public ProgressRequestBody(RequestBody requestBody, UploadProgressListener progressListener) {    this.requestBody = requestBody;    this.progressListener = progressListener;  }  /**   * 重写调用实际的响应体的contentType   * @return MediaType   */  @Override  public MediaType contentType() {    return requestBody.contentType();  }  /**   * 重写调用实际的响应体的contentLength   * @return contentLength   * @throws IOException 异常   */  @Override  public long contentLength() throws IOException {    return requestBody.contentLength();  }  /**   * 重写进行写入   * @param sink BufferedSink   * @throws IOException 异常   */  @Override  public void writeTo(BufferedSink sink) throws IOException {    if (null == bufferedSink) {      bufferedSink = Okio.buffer(sink(sink));    }    requestBody.writeTo(bufferedSink);    //必须调用flush,否则最后一部分数据可能不会被写入    bufferedSink.flush();  }  /**   * 写入,回调进度接口   * @param sink Sink   * @return Sink   */  private Sink sink(Sink sink) {    return new ForwardingSink(sink) {      //当前写入字节数      long writtenBytesCount = 0L;      //总字节长度,避免多次调用contentLength()方法      long totalBytesCount = 0L;      @Override      public void write(Buffer source, long byteCount) throws IOException {        super.write(source, byteCount);        //增加当前写入的字节数        writtenBytesCount += byteCount;        //获得contentLength的值,后续不再调用        if (totalBytesCount == 0) {          totalBytesCount = contentLength();        }        Observable.just(writtenBytesCount).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Long>() {          @Override          public void call(Long aLong) {            progressListener.onProgress(writtenBytesCount, totalBytesCount);          }        });      }    };  }}

3自定义接口,回调progress进度

public interface UploadProgressListener {  /**   * 上传进度   * @param currentBytesCount   * @param totalBytesCount   */  void onProgress(long currentBytesCount, long totalBytesCount);}

4创建RequestBody对象,加入进度

 File file=new File("/storage/emulated/0/Download/11.jpg");   RequestBody requestBody=RequestBody.create(MediaType.parse("image/jpeg"),file);   MultipartBody.Part part= MultipartBody.Part.createFormData("file_name", file.getName(), new ProgressRequestBody(requestBody,       new UploadProgressListener() {     @Override     public void onProgress(long currentBytesCount, long totalBytesCount) {       tvMsg.setText("提示:上传中");       progressBar.setMax((int) totalBytesCount);       progressBar.setProgress((int) currentBytesCount);     }   }));

5.传递附带信息

和封装二中post请求的方式一样,我们需要继承baseentity,复写里面的方法,然后设置需要传递的参数,因为是测试接口,所以我的参数直接写死在entity里面,part文件动态指定

/** * 上传请求api * Created by WZG on 2016/10/20. */public class UplaodApi extends BaseEntity {  /*需要上传的文件*/  private MultipartBody.Part part;  public UplaodApi(HttpOnNextListener listener, RxAppCompatActivity rxAppCompatActivity) {    super(listener, rxAppCompatActivity);    setShowProgress(true);  }  public MultipartBody.Part getPart() {    return part;  }  public void setPart(MultipartBody.Part part) {    this.part = part;  }  @Override  public Observable getObservable(HttpService methods) {    RequestBody uid= RequestBody.create(MediaType.parse("text/plain"), "4811420");    RequestBody key = RequestBody.create(MediaType.parse("text/plain"), "21f8d9bcc50c6ac1ae1020ce12f5f5a7");    return methods.uploadImage(uid,key,getPart());  }}

6.post请求处理

请求和封装二中的请求一样,通过传递一个指定的HttpOnNextListener 对象来回调来监听结果信息,一一对应

 private void uploadeDo(){   File file=new File("/storage/emulated/0/Download/11.jpg");   RequestBody requestBody=RequestBody.create(MediaType.parse("image/jpeg"),file);   MultipartBody.Part part= MultipartBody.Part.createFormData("file_name", file.getName(), new ProgressRequestBody(requestBody,       new UploadProgressListener() {     @Override     public void onProgress(long currentBytesCount, long totalBytesCount) {       tvMsg.setText("提示:上传中");       progressBar.setMax((int) totalBytesCount);       progressBar.setProgress((int) currentBytesCount);     }   }));   UplaodApi uplaodApi = new UplaodApi(httpOnNextListener,this);   uplaodApi.setPart(part);   HttpManager manager = HttpManager.getInstance();   manager.doHttpDeal(uplaodApi); }  /**   * 上传回调   */  HttpOnNextListener httpOnNextListener=new HttpOnNextListener<UploadResulte>() {    @Override    public void onNext(UploadResulte o) {      tvMsg.setText("成功");      Glide.with(MainActivity.this).load(o.getHeadImgUrl()).skipMemoryCache(true).into(img);    }    @Override    public void onError(Throwable e) {      super.onError(e);      tvMsg.setText("失败:"+e.toString());    }  };

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表