曾经在代码里放荡不羁,如今在博文中日夜兼行,只为今天与你分享成果。如果觉得本文有用,记得关注我,我将带给你更多。

还没看过第一篇文章的欢迎移步:OkHttp 优雅封装 HttpUtils 之气海雪山初探

介绍

HttpUtils 是近期开源的对 OkHttp 轻量封装的框架,它独创的异步预处理器,特色的标签,灵活的上传下载进度监听与过程控制功能,在轻松解决很多原本令人头疼问题的同时,设计上也力求纯粹与优雅。

  • 链式调用,一点到底
  • BaseURL、URL占位符、JSON自动封装与解析
  • 同步拦截器、异步预处理器、回调执行器
  • 文件上传下载(过程控制、进度监听)
  • TCP连接池、Http2

中文官网:http://okhttps.ejlchina.com/

项目地址

Gitee:https://gitee.com/ejlchina-zhxu/httputils

GitHub:https://github.com/ejlchina/httputils

安装教程

Maven

<dependency>
<groupId>com.ejlchina</groupId>
<artifactId>httputils</artifactId>
<version>2.2.0</version>
</dependency>

Gradle

compile 'com.ejlchina:httputils:2.2.0'

  在正式开始之前,我们依然假设,下文中出现http均是在构建时设置了BaseUrl的HTTP实例(详细请看前文):

HTTP http = HTTP.builder()
.baseUrl("http://api.demo.com")
.build();

OK,一切就绪,我们接着上篇文章继续讲。

8 文件下载

  HttpUtils 并没有把文件的下载排除在常规的请求之外,而是使用同一套API,它优雅的设计使得下载与常规请求融合的毫无违和感,一个简单的示例:

http.sync("/download/test.zip")
.get() // 使用 GET 方法(其它方法也可以,看服务器支持)
.getBody() // 得到报文体
.toFolder("D:/download") // 下载到指定目录,文件名将根据下载信息自动生成
.start(); // 启动下载

  或使用异步请求方式:

http.async("/download/test.zip")
.setOnResponse((HttpResult result) -> {
// 下载到指定路径
result.getBody().toFile("D:/download/test.zip").start();
})
.get();

  这里要说明一下:sync与async的区别在于连接服务器并得到响应这个过程的同步与异步(这个过程的耗时在大文件下载中占比极小),而start方法启动的下载过程则都是异步的。

8.1 下载进度监听

  就直接上代码啦,相信诸君一看便懂:

http.sync("/download/test.zip")
.get()
.getBody()
.setStepBytes(1024) // 设置每接收 1024 个字节执行一次进度回调(不设置默认为 8192)
// .setStepRate(0.01) // 设置每接收 1% 执行一次进度回调(不设置以 StepBytes 为准)
.setOnProcess((Process process) -> { // 下载进度回调
long doneBytes = process.getDoneBytes(); // 已下载字节数
long totalBytes = process.getTotalBytes(); // 总共的字节数
double rate = process.getRate(); // 已下载的比例
boolean isDone = process.isDone(); // 是否下载完成
})
.toFolder("D:/download/") // 指定下载的目录,文件名将根据下载信息自动生成
// .toFile("D:/download/test.zip") // 指定下载的路径,若文件已存在则覆盖
.setOnSuccess((File file) -> { // 下载成功回调 })
.start();

  值得一提的是:由于 HttpUtils 并没有把下载做的很特别,这里设置的进度回调不只对下载文件起用作,即使对响应JSON的常规请求,只要设置了进度回调,它也会告诉你报文接收的进度(提前是服务器响应的报文有Content-Length头),例如:

List<User> users = http.sync("/users")
.get()
.getBody()
.setStepBytes(2)
.setOnProcess((Process process) -> {
System.out.println(process.getRate());
})
.toList(User.class);

8.2 下载过程控制

  过于简单:还是直接上代码:

Ctrl ctrl = http.sync("/download/test.zip")
.get()
.getBody()
.setOnProcess((Process process) -> {
System.out.println(process.getRate());
})
.toFolder("D:/download/")
.start(); // 该方法返回一个下载过程控制器 ctrl.status(); // 下载状态
ctrl.pause(); // 暂停下载
ctrl.resume(); // 恢复下载
ctrl.cancel(); // 取消下载(同时会删除文件,不可恢复)

  无论是同步还是异步发起的下载请求,都可以做以上的控制:

http.async("/download/test.zip")
.setOnResponse((HttpResult result) -> {
// 拿到下载控制器
Ctrl ctrl = result.getBody().toFolder("D:/download/").start();
})
.get();

8.3 实现断点续传

  HttpUtils 对断点续传并没有再做更高层次的封装,因为这是app该去做的事情,它在设计上使各种网络问题的处理变简单的同时力求纯粹。下面的例子可以看到,HttpUtils 通过一个失败回调拿到断点,便将复杂的问题变得简单:

http.sync("/download/test.zip")
.get()
.getBody()
.toFolder("D:/download/")
.setOnFailure((Failure failure) -> { // 下载失败回调,以便接收诸如网络错误等失败信息
IOException e = failure.getException(); // 具体的异常信息
long doneBytes = failure.getDoneBytes(); // 已下载的字节数(断点),需要保存,用于断点续传
File file = failure.getFile(); // 下载生成的文件,需要保存 ,用于断点续传(只保存路径也可以)
})
.start();

  然后实现断点续传:

long doneBytes = ...    // 拿到保存的断点
File file = ... // 待续传的文件 http.sync("/download/test.zip")
.setRange(doneBytes) // 设置断点(已下载的字节数)
.get()
.getBody()
.toFile(file) // 下载到同一个文件里
.setAppended() // 开启文件追加模式
.setOnSuccess((File file) -> { })
.setOnFailure((Failure failure) -> { })
.start();

8.4 实现分块下载

  当文件很大时,有时候我们会考虑分块下载,与断点续传的思路是一样的,示例代码:

static String url = "http://api.demo.com/download/test.zip"

public static void main(String[] args) {
long totalSize = HttpUtils.sync(url).get().getBody()
.close() // 因为这次请求只是为了获得文件大小,不消费报文体,所以直接关闭
.getContentLength(); // 获得待下载文件的大小(由于未消费报文体,所以该请求不会消耗下载报文体的时间和网络流量)
download(totalSize, 0); // 从第 0 块开始下载
sleep(50000); // 等待下载完成(不然本例的主线程就结束啦)
} static void download(long totalSize, int index) {
long size = 3 * 1024 * 1024; // 每块下载 3M
long start = index * size;
long end = Math.min(start + size, totalSize);
HttpUtils.sync(url)
.setRange(start, end) // 设置本次下载的范围
.get().getBody()
.toFile("D:/download/test.zip") // 下载到同一个文件里
.setAppended() // 开启文件追加模式
.setOnSuccess((File file) -> {
if (end < totalSize) { // 若未下载完,则继续下载下一块
download(totalSize, index + 1);
} else {
System.out.println("下载完成");
}
})
.start();
}

本例中使用了HttpUtils类,关于它的详细介绍,请看前文:OkHttp 优雅封装 HttpUtils 之 气海雪山初探。

9 文件上传

  一个简单文件上传的示例:

http.sync("/upload")
.addFileParam("test", "D:/download/test.zip")
.post() // 上传发法一般使用 POST 或 PUT,看服务器支持

  异步上传也是完全一样:

http.async("/upload")
.addFileParam("test", "D:/download/test.zip")
.post()

9.1 上传进度监听

   HttpUtils 的上传进度监听,监听的是所有请求报文体的发送进度,示例代码:

http.sync("/upload")
.addBodyParam("name", "Jack")
.addBodyParam("age", 20)
.addFileParam("avatar", "D:/image/avatar.jpg")
.setStepBytes(1024) // 设置每发送 1024 个字节执行一次进度回调(不设置默认为 8192)
// .setStepRate(0.01) // 设置每发送 1% 执行一次进度回调(不设置以 StepBytes 为准)
.setOnProcess((Process process) -> { // 上传进度回调
long doneBytes = process.getDoneBytes(); // 已发送字节数
long totalBytes = process.getTotalBytes(); // 总共的字节数
double rate = process.getRate(); // 已发送的比例
boolean isDone = process.isDone(); // 是否发送完成
})
.post()

  咦!怎么感觉和下载的进度回调的一样?没错!HttpUtils 还是使用同一套API处理上传和下载的进度回调,区别只在于上传是在get/post方法之前使用这些API,下载是在getBody方法之后使用。很好理解:get/post之前是准备发送请求时段,有上传的含义,而getBody之后,已是报文响应的时段,当然是下载。

9.2 上传过程控制

  上传文件的过程控制就很简单,和常规请求一样,只有异步发起的上传可以取消:

HttpCall call = http.async("/upload")
.addFileParam("test", "D:/download/test.zip")
.setOnProcess((Process process) -> {
System.out.println(process.getRate());
})
.post() call.cancel(); // 取消上传

  上传就没有暂停和继续这个功能啦,应该没人有这个需求吧?

前篇文章:OkHttp 优雅封装 HttpUtils 之 气海雪山初探

下篇文章:OkHttp 优雅封装 HttpUtils 之 回调线程魔变


曾经在代码里放荡不羁,如今在博文中日夜兼行,只为今天与你分享成果。如果觉得本文有用,记得关注我,我将带给你更多。

OkHttp 优雅封装 HttpUtils 之 上传下载解密的更多相关文章

  1. OkHttp 优雅封装 HttpUtils 之 气海雪山初探

    曾经在代码里放荡不羁,如今在博文中日夜兼行,只为今天与你分享成果.如果觉得本文有用,记得关注我,我将带给你更多. 介绍 HttpUtils 是近期开源的对 OkHttp 轻量封装的框架,它独创的异步预 ...

  2. Android okHttp网络请求之文件上传下载

    前言: 前面介绍了基于okHttp的get.post基本使用(http://www.cnblogs.com/whoislcj/p/5526431.html),今天来实现一下基于okHttp的文件上传. ...

  3. Android使用OkHttp实现带进度的上传下载

    先贴上MainActivity.java package cn.edu.zafu.sample; import android.os.Bundle; import android.support.v7 ...

  4. Java java httpclient4.5 进行http,https通过SSL安全验证跳过,封装接口请求 get,post(formdata,json)封装,文件上传下载

    package api; import java.util.*; import java.net.URI; import org.apache.http.Consts; import org.apac ...

  5. OkHttp 优雅封装 OkHttps 之 回调线程魔变

    第一篇:OkHttp 优雅封装 HttpUtils 之 气海雪山初探 第二篇:OkHttp 优雅封装 HttpUtils 之 上传下载解密 简介 HttpUtils 从 v2.3.0 之后便重命名了, ...

  6. RxHttp 完美适配Android 10/11 上传/下载/进度监听

    1.前言 随着Android 11的正式发布,适配Android 10/11 分区存储就更加的迫切了,因为Android 11开始,将强制开启分区存储,我们就无法再以绝对路径的方式去读写非沙盒目录下的 ...

  7. SpringMVC文件上传下载

    在Spring MVC的基础框架搭建起来后,我们测试了spring mvc中的返回值类型,如果你还没有搭建好springmvc的架构请参考博文->http://www.cnblogs.com/q ...

  8. servlet上传下载(任何格式的都可以)

    jar不能低于此版本,JDK1.6以上,否则户报错 <dependency> <groupId>commons-fileupload</groupId> <a ...

  9. Webwork 学习之路【07】文件上传下载

    Web上传和下载应该是很普遍的一个需求,无论是小型网站还是大并发访问的交易网站.WebWork 当然也提供了很友好的拦截器来实现对文件的上传,让我们可以专注与业务逻辑的设计和实现,在实现上传和下载时顺 ...

随机推荐

  1. Reverse Subarray To Maximize Array Value

    2020-02-03 20:43:46 问题描述: 问题求解: public boolean canTransform(String start, String end) { int n = star ...

  2. Ubuntu环境下部署Django+uwsgi+nginx总结

    前言 这是我在搭建Django项目时候的过程,拿来总结记录,以备不时之需. 项目采用nginx+uwsgi的搭配方式. 项目依赖包采用requirements.txt文件管理的方式. 本地准备工作 确 ...

  3. 给rm命令加保险

    众所周知,脑残可以学习,但是手残没法治.相信每一位喜欢用终端操作电脑的同学都曾手误使用 rm 命令把不该删除的文件删了.然而,使用 rm 删除的文件是不会进去回收站的. 所以,最好的方法就是我们自定义 ...

  4. Apple的Core ML3简介——为iPhone构建深度学习模型(附代码)

    概述 Apple的Core ML 3是一个为开发人员和程序员设计的工具,帮助程序员进入人工智能生态 你可以使用Core ML 3为iPhone构建机器学习和深度学习模型 在本文中,我们将为iPhone ...

  5. ConcurrentHashMap1.7和1.8的源码分析比较

    ConcurrentHashMap 在多线程环境下,使用HashMap进行put操作时存在丢失数据的情况,为了避免这种bug的隐患,强烈建议使用ConcurrentHashMap代替HashMap,为 ...

  6. spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(02)

    在上篇博客中写道了bean后置处理器InstantiationAwareBeanPostProcessor,只介绍了其中一个方法的作用及用法,现在来看postProcessBeforeInstanti ...

  7. Django-on_delete

    一.外键的删除 关于on_delete的总结 1.常见的使用方式(设置为null) class BookModel(models.Model): """ 书籍表 &quo ...

  8. Django之extra过滤

    extra extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None) 有些 ...

  9. 版本控制git的简单使用

    0.第一次使用时配置: git config --global user.name "your_name" git config --global user.email " ...

  10. HDU1074:Doing Homework(状压DP)

    Doing Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...