当前位置: 移动技术网 > 移动技术>移动开发>Android > RxJava+Retrofit+OkHttp实现文件上传

RxJava+Retrofit+OkHttp实现文件上传

2019年07月24日  | 移动技术网移动技术  | 我要评论

背景

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

效果

实现

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

  };

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网