retrofit2+okhttp3图片上传及进度监听

2023-12-07 13:48

本文主要是介绍retrofit2+okhttp3图片上传及进度监听,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、使用jar包

由于retrofit2与1的写法有很大的变化,并且对okhttp存在着依赖。所以需要确定选择使用方向,以免陷入不必要的坑中。

本篇讲采用retrofit2 + okhttp3做结合使用。在导包过程中本人也遇到了一些不兼容的麻烦,再此做记录。

retrofit-2.1.0.jar、okhttp-3.4.1.jar、okio-1.6.0.jar、converter-gson-2.1.0.jar

另外我们服务端使用springmvc框架,通过@responseBody返回。前期引入gson包为gson-2.4.jar总报错不知何故,最后换成gson-2.7.jar就可以了。

2、使用retrofit

retrofit使用是有一定规律性,我们可以将其归纳后提出,封装一个针对retrofit的制造者。

public class RetrofitBuilder{private static Retrofit retrofit;public synchronized static Retrofit buildRetrofit(String url){if(retrofit == null){OkHttpClient client = new OkHttpClient.Builder().retryOnConnectionFailure(true).build();retrofit = new Retrofit.Builder.client(client).baseUrl(url).addConverterFactory((GsonConverterFactory.create())).build();}return retrofit;}
}
retrofit对应请求接口

public interface FileuploadService{/***@param parts*@param map(请求参数)*@return(JsonRetrun实体类)*/@Multipart@POST("uploader")Call<JsonReturn> uploadFilesWithParts(@Part() List<MultipartBody.Part> parts , @QueryMap Map<String , String> map);/***@param body*@param map(请求参数)*@return(JsonRetrun实体类)*/@Multipart@POST("uploader")Call<JsonReturn> uploadFilesWithBody(@Body() MultipartBody body , @QueryMap Map<String , String> map);
}
回执泛型实体类
public class JsonReturn{private String errcode;private String errmsg;private String msg;private Object object;set/get方法.....
}
接口中Multipart参数生成,可以封装一个创造者。

public class MultipartBuiler{public static MultipartBody filesToBody(List<File> files , RetrofitCallback<JsonReturn> callback){for(File file : files){RequestBody requestBody = RequestBody.create(MediaType.parse("img/png"),file);FileRequestBody body = new FileRequestBody(reqeustBody , callback , file);builder.addFormDataPart("file" , file.getName , body);}builder.setType(MultipartBody.FORM);MultipartBody multipartBody = builder.build();return multipartBody;}public staitc List<MultipartBody.Part> filesToParts(List<File> files , RetrofitCallback<JsonReturn> callback){List<MultipartBody.Part> parts = new ArrayList<>(files.size());for(File file : files){RequestBody requestBody = RequestBody.create(MediaType.parse("img/png"),file);FileRequestBody body = new FileRequestBody(reqeustBody , callback , file);MultipartBody.Part part = MultipartBody.Part.createFormData("file" , file.getName() , body);parts.add(part);}return parts;}
}
以上可以实现文件的上传了。

3、有的时候我们在项目中需要监听文件的上传进度,那要如何实现呢。继续往下看思路。

上传的过程,我们可以考虑为request的交互过程,所以我们完全可以针对okhttp中的requestBody做些扩展。

/*** 扩展Okhttp的请求体, 实现上传时的进度监听* @author xuximing** @param <T>*/
public class FileRequestBody<T> extends RequestBody {/*** 实体请求体*/private RequestBody requestBody;/*** 上传回调接口*/private RetrofitCallback<T> callback;/*** 文件*/private File file ;/*** 包装完成的BufferedSink*/private BufferedSink bufferedSink;public FileRequestBody(RequestBody requestBody , RetrofitCallback<T> callback , File file){super();this.requestBody = requestBody;this.callback = callback;this.file = file;}@Overridepublic long contentLength() throws IOException {return requestBody.contentLength();}@Overridepublic MediaType contentType() {return requestBody.contentType();}@Overridepublic void writeTo(BufferedSink sink) throws IOException {if(bufferedSink == null){//包装bufferedSink = Okio.buffer(sink(sink));}//写入requestBody.writeTo(bufferedSink);//必须调用flush,否则最后一部分数据可能不会被写入bufferedSink.flush();}/*** 写入,回调进度接口* @param sink* @return*/private Sink sink(Sink sink){return new ForwardingSink(sink) {//当前写入字节数long bytesWritten = 0L;//总字节长度,避免多次调用contentLength()方法long contentLength = 0L;@Overridepublic void write(Buffer source, long byteCount) throws IOException {super.write(source, byteCount);if(contentLength == 0){//获得contentLength的值,后续不再调用contentLength = contentLength();}//增加当前写入的字节数bytesWritten += byteCount;//回调callback.onLoading(file , contentLength, bytesWritten);}};}
}
retrofit中callback不能完全满足我们的需求,我们也可以进一步扩展

public abstract class RetrofitCallback<T> implements Callback<T>{@Overridepublic void onResponse(Call<T> call, Response<T> response) {if(response.isSuccessful()){onSuccess(call, response);}else{onFailure(call, new Throwable(response.message()));}}public abstract void onSuccess(Call<T> call , Response<T> response);public void onLoading(File file , long total , long progress){}
}

4、最终使用

使用起来用到的代码依旧相同,那我们在次提取封装

public class UploadFileUitl{public UploadFileUitl(String url , Map<> paramMap , List mList , RetrofitCallBack callback){List<MultipartBody.Part> parts = MultipartBuilder.filesToParts(mList , callback);//创建Multipart//创建Retrofit,并调用enqueue实现异步操作RetrofitBuilder.buildRetrofit(url).create(FileUploadService.class)'.uploadFilesWithParts(parts , paramMap).enqueue(callback);}
}

ok,开始最终的调用吧

new UploadFileUtil(url , paramMap , fileList , new RetrofitCallback(){//成功@Overridepublic void onSuccess(Call call , Response response){}//失败@Overridepublic void onFailure(Call call , Throwable t){}//加载中@Overridepublic void onLoading(File file , long total , long progress){}
});

不要忘记android的规则,对一些耗时操作不要放在主线程中。因此我们还需要将最终调用放到子线程中。我用的是AsyncTask

class UploadTask extends AsyncTask<Map , Map , Object>{//在执行过程中调用上传监听过程@Overrideprotected Object doInBackground(Map... params){new UploadFileUtil(url , paramMap , fileList , new RetrofitCallback(){//成功@Overridepublic void onSuccess(Call call , Response response){}//失败@Overridepublic void onFailure(Call call , Throwable t){}//加载中@Overridepublic void onLoading(File file , long total , long progress){....publishProgress(map);//出发处理进度}});}//处理进度@Overrideprotected void onProgressUpdate(Map... maps){}
}




 


这篇关于retrofit2+okhttp3图片上传及进度监听的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/466111

相关文章

C#实现添加/替换/提取或删除Excel中的图片

《C#实现添加/替换/提取或删除Excel中的图片》在Excel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更加美观,下面我们来看看如何在C#中实现添加/替换/提取或删除E... 在Excandroidel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更

C#中图片如何自适应pictureBox大小

《C#中图片如何自适应pictureBox大小》文章描述了如何在C#中实现图片自适应pictureBox大小,并展示修改前后的效果,修改步骤包括两步,作者分享了个人经验,希望对大家有所帮助... 目录C#图片自适应pictureBox大小编程修改步骤总结C#图片自适应pictureBox大小上图中“z轴

使用Python将长图片分割为若干张小图片

《使用Python将长图片分割为若干张小图片》这篇文章主要为大家详细介绍了如何使用Python将长图片分割为若干张小图片,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果1. Python需求

Java文件上传的多种实现方式

《Java文件上传的多种实现方式》文章主要介绍了文件上传接收接口的使用方法,包括获取文件信息、创建文件夹、保存文件到本地的两种方法,以及如何使用Postman进行接口调用... 目录Java文件上传的多方式1.文件上传接收文件接口2.接口主要内容部分3.postman接口调用总结Java文件上传的多方式1

使用Python实现大文件切片上传及断点续传的方法

《使用Python实现大文件切片上传及断点续传的方法》本文介绍了使用Python实现大文件切片上传及断点续传的方法,包括功能模块划分(获取上传文件接口状态、临时文件夹状态信息、切片上传、切片合并)、整... 目录概要整体架构流程技术细节获取上传文件状态接口获取临时文件夹状态信息接口切片上传功能文件合并功能小

使用 Python 和 LabelMe 实现图片验证码的自动标注功能

《使用Python和LabelMe实现图片验证码的自动标注功能》文章介绍了如何使用Python和LabelMe自动标注图片验证码,主要步骤包括图像预处理、OCR识别和生成标注文件,通过结合Pa... 目录使用 python 和 LabelMe 实现图片验证码的自动标注环境准备必备工具安装依赖实现自动标注核心

SpringBoot整合Canal+RabbitMQ监听数据变更详解

《SpringBoot整合Canal+RabbitMQ监听数据变更详解》在现代分布式系统中,实时获取数据库的变更信息是一个常见的需求,本文将介绍SpringBoot如何通过整合Canal和Rabbit... 目录需求步骤环境搭建整合SpringBoot与Canal实现客户端Canal整合RabbitMQSp

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

Java操作xls替换文本或图片的功能实现

《Java操作xls替换文本或图片的功能实现》这篇文章主要给大家介绍了关于Java操作xls替换文本或图片功能实现的相关资料,文中通过示例代码讲解了文件上传、文件处理和Excel文件生成,需要的朋友可... 目录准备xls模板文件:template.xls准备需要替换的图片和数据功能实现包声明与导入类声明与

基于C#实现将图片转换为PDF文档

《基于C#实现将图片转换为PDF文档》将图片(JPG、PNG)转换为PDF文件可以帮助我们更好地保存和分享图片,所以本文将介绍如何使用C#将JPG/PNG图片转换为PDF文档,需要的可以参考下... 目录介绍C# 将单张图片转换为PDF文档C# 将多张图片转换到一个PDF文档介绍将图片(JPG、PNG)转