热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

RxJava+Retrofit+OkHttp实现文件上传

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

背景

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

效果

实现

1.定义service接口

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

  /*上传文件*/
  @Multipart
  @POST("AppYuFaKu/uploadHeadImg")
  Observable> 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() {
          @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() {
    @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());
    }

  };

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


推荐阅读
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Linuxchmod目录权限命令图文详解在Linux文件系统模型中,每个文件都有一组9个权限位用来控制谁能够读写和执行该文件的内容。对于目录来说,执行位的作用是控制能否进入或者通过 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • Lodop中特殊符号打印设计和预览样式不同的问题解析
    本文主要解析了在Lodop中使用特殊符号打印设计和预览样式不同的问题。由于调用的本机ie引擎版本可能不同,导致在不同浏览器下样式解析不同。同时,未指定文字字体和样式设置也会导致打印设计和预览的差异。文章提出了通过指定具体字体和样式来解决问题的方法,并强调了以打印预览和虚拟打印机测试为准。 ... [详细]
  • 安装mysqlclient失败解决办法
    本文介绍了在MAC系统中,使用django使用mysql数据库报错的解决办法。通过源码安装mysqlclient或将mysql_config添加到系统环境变量中,可以解决安装mysqlclient失败的问题。同时,还介绍了查看mysql安装路径和使配置文件生效的方法。 ... [详细]
  • Final关键字的含义及用法详解
    本文详细介绍了Java中final关键字的含义和用法。final关键字可以修饰非抽象类、非抽象类成员方法和变量。final类不能被继承,final类中的方法默认是final的。final方法不能被子类的方法覆盖,但可以被继承。final成员变量表示常量,只能被赋值一次,赋值后值不再改变。文章还讨论了final类和final方法的应用场景,以及使用final方法的两个原因:锁定方法防止修改和提高执行效率。 ... [详细]
  • 本文介绍了求解gcdexgcd斐蜀定理的迭代法和递归法,并解释了exgcd的概念和应用。exgcd是指对于不完全为0的非负整数a和b,gcd(a,b)表示a和b的最大公约数,必然存在整数对x和y,使得gcd(a,b)=ax+by。此外,本文还给出了相应的代码示例。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • Microsoft Office for Mac最新版本安装教程,亲测可用!
    本文介绍了Microsoft Office for Mac最新版本的安装教程,经过亲测可用。Office工具是办公必备的工具,它为用户和企业设计,可以利用功能强大的Outlook处理电子邮件、日历和通讯录事宜。安装包包括Word、Excel、PPT、OneNote和Outlook。阅读本文可以了解如何下载并安装Office,以及安装过程中的注意事项。安装完毕后,可以正常使用Office中的Word等功能。 ... [详细]
  • 电销机器人作为一种人工智能技术载体,可以帮助企业提升电销效率并节省人工成本。然而,电销机器人市场缺乏统一的市场准入标准,产品品质良莠不齐。创业者在代理或购买电销机器人时应注意谨防用录音冒充真人语音通话以及宣传技术与实际效果不符的情况。选择电销机器人时需要考察公司资质和产品品质,尤其要关注语音识别率。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
author-avatar
海带木耳求_529
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有