快捷搜索:  汽车  科技

android网络请求进度条:5分钟带你搞懂OkHttp断点上传

android网络请求进度条:5分钟带你搞懂OkHttp断点上传有了FileRequestBody类,我们只需要传入一个断点位置,剩下的工作就跟普通的文件上传一样。 接下来,直接进入代码实现。//为简化阅读,已省略部分代码 public class FileRequestBody extends RequestBody { private final File file; private final long skipSize; //断点位置 private final MediaType mediaType; public FileRequestBody(File file long skipSize @Nullable MediaType mediaType) { this.file = file; this.skipSize = skipSize; this

作者:刘一刀

经常会有同学问:文件的断点上传如何实现?

断点上传/下载,这是在客户端经常遇到的场景,当我们需要上传或下载一个大文件时,都会考虑使用断点续传的方式。

断点上传相较于断点下载来说,最大的区别就在于断点位置的记录,上传记录在服务端,下载记录在客户端,因此,客户端需要在上传前,通过接口去拿到文件的断点位置,然后在上传时,将文件输入流跳转到断点位置

一、准备工作

对于文件上传,其实就是打开文件的输入流,不停的读取数据到byte数组中,随后写出到服务端;那客户端要做的就是跳过已经上传的部分,也就是直接跳到断点位置,这样就可以从断点位置去读取数据,也就达到了断点上传的目的。

伪代码如下:

String filePath = "..."; long skipSize = 100; //假设断点位置是 100 byte InputStream input = input = new FileInputStream(filePath); input.skip(skipSize) //跳转到断点位置

然而,OkHttp并没有直接提供设置断点的方法,所以需要客户端自定义RequestBody,取名为FileRequestBody,如下:

//为简化阅读,已省略部分代码 public class FileRequestBody extends RequestBody { private final File file; private final long skipSize; //断点位置 private final MediaType mediaType; public FileRequestBody(File file long skipSize @Nullable MediaType mediaType) { this.file = file; this.skipSize = skipSize; this.mediaType = mediaType; } @Override public long contentLength() throws IOException { return file.length() - skipSize; } @Override public void writeTo(@NotNull BufferedSink sink) throws IOException { InputStream input = null; Source source = null; try { input = new FileInputStream(file); if (skipSize > 0) { input.skip(skipSize); //跳到断点位置 } source = Okio.source(input); sink.writeAll(source); } finally { OkHttpCompat.closeQuietly(source input); } } }

为方便阅读,以上省略部分源码,FileRequestBody类完整源码

有了FileRequestBody类,我们只需要传入一个断点位置,剩下的工作就跟普通的文件上传一样。 接下来,直接进入代码实现。

二、代码实现2.1 获取断点位置

首先,需要服务端提供一个接口,通过userId去查找该用户未上传完成的任务列表,代码如下:

RxHttp.get("/.../getToUploadTask") .add("userId" "88888888") .asList<ToUploadTask>() .subscribe({ //成功回调,这里通过 it 拿到 List<ToUploadTask> } { //异常回调 });

其中ToUploadTask类如下:

//待上传任务 data class ToUploadTask( val md5: String //文件的md5,用于验证文件的唯一性 val filePath: String //文件在客户端的绝对路径 val skipSize: Long = 0 //断点位置 )

注:md5、filePath 这两个参数需要客户端在文件上传时传递给服务端,用于对文件的校验,防止文件错乱

2.2 断点上传

有了待上传任务,客户端就可以执行断点上传操作,OkHttp代码如下:

fun uploadFile(uploadTask: ToUploadTask) { //1.校验文件是否存在 val file = File(uploadTask.filePath) if (!file.exists() && !file.isFile) return //2.校验文件的 md5 值 val fileMd5 = FileUtils.getFileMD5ToString(file) if (!fileMd5.equals(uploadTask.md5)) return //3.构建请求体 val fileRequestBody = FileRequestBody(file uploadTask.skipSize BuildUtil.getMediaType(file.name)) val multipartBody = MultipartBody.Builder() .addFormDataPart("userId" "88888888") .addFormDataPart("md5" fileMd5) .addFormDataPart("filePath" file.absolutePath) .addFormDataPart("file" file.name fileRequestBody) //添加文件body .build() //4.构建请求 val request = Request.Builder() .url("/.../uploadFile") .post(multipartBody) .build() //5.执行请求 val okClient = OkHttpClient.Builder().build() okClient.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call e: IOException) { //异常回调 } override fun onResponse(call: Call response: Response) { //成功回调 } }) }

FIleUtils源码,BuildUtil源码

当然,考虑到很少人会直接使用OkHttp,所以这里也贴出RxHttp的实现代码,很简单,仅需构建一个UpFile对象即可,就可很方便的监听上传进度,代码如下:

fun uploadFile(uploadTask: ToUploadTask) { //1.校验文件是否存在 val file = File(uploadTask.filePath) if (!file.exists() && !file.isFile) return //2.校验文件的 md5 值 val fileMd5 = FileUtils.getFileMD5ToString(file) if (!fileMd5.equals(uploadTask.md5)) return val upFile = UpFile("file" file file.name uploadTask.skipSize) //3.直接上传 RxHttp.postForm("/.../uploadFile") .add("userId" "88888888") .add("md5" fileMd5) .add("filePath" file.absolutePath) .addFile(upFile) .upload(AndroidSchedulers.mainThread()) { //上传进度回调 } .asString() .subscribe({ //成功回调 } { //异常回调 }) } 小结

断点上传相较普通的文件上传,客户端多了一个断点的设置,大部分工作量在服务端,服务端不仅需要处理文件的拼接逻辑,还需记录未上传完成的任务,并通过接口暴露给客户端。

在这里还分享一份由大佬亲自收录整理的学习PDF 架构视频 面试文档 源码笔记高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料

这些都是我现在闲暇时还会反复翻阅的精品资料。里面对近几年的大厂面试高频知识点都有详细的讲解。相信可以有效地帮助大家掌握知识、理解原理,帮助大家在未来取得一份不错的答卷。

当然,你也可以拿去查漏补缺,提升自身的竞争力。

真心希望可以帮助到大家,Android路漫漫,共勉!

如果你有需要的话,只需私信我【进阶】即可获取

android网络请求进度条:5分钟带你搞懂OkHttp断点上传(1)

android网络请求进度条:5分钟带你搞懂OkHttp断点上传(2)

android网络请求进度条:5分钟带你搞懂OkHttp断点上传(3)

猜您喜欢: