欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

RxJava+Retrofit+OkHttp实现文件上传

程序员文章站 2022-06-19 18:55:57
背景 在实际运用中上传是一个必不可少的功能,所以我们在封装二的基础上加入上传的功能,同时需要附带上传进度! 效果 实现 1.定义service接口 注意:mu...

背景

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

效果

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());
    }

  };

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