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

相关文章

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

基于Python开发批量提取Excel图片的小工具

《基于Python开发批量提取Excel图片的小工具》这篇文章主要为大家详细介绍了如何使用Python中的openpyxl库开发一个小工具,可以实现批量提取Excel图片,有需要的小伙伴可以参考一下... 目前有一个需求,就是批量读取当前目录下所有文件夹里的Excel文件,去获取出Excel文件中的图片,并

Java实现数据库图片上传与存储功能

《Java实现数据库图片上传与存储功能》在现代的Web开发中,上传图片并将其存储在数据库中是常见的需求之一,本文将介绍如何通过Java实现图片上传,存储到数据库的完整过程,希望对大家有所帮助... 目录1. 项目结构2. 数据库表设计3. 实现图片上传功能3.1 文件上传控制器3.2 图片上传服务4. 实现

使用mvn deploy命令上传jar包的实现

《使用mvndeploy命令上传jar包的实现》本文介绍了使用mvndeploy:deploy-file命令将本地仓库中的JAR包重新发布到Maven私服,文中通过示例代码介绍的非常详细,对大家的学... 目录一、背景二、环境三、配置nexus上传账号四、执行deploy命令上传包1. 首先需要把本地仓中要

Java实现数据库图片上传功能详解

《Java实现数据库图片上传功能详解》这篇文章主要为大家详细介绍了如何使用Java实现数据库图片上传功能,包含从数据库拿图片传递前端渲染,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、前言2、数据库搭建&nbsChina编程p; 3、后端实现将图片存储进数据库4、后端实现从数据库取出图片给前端5、前端拿到

Flutter监听当前页面可见与隐藏状态的代码详解

《Flutter监听当前页面可见与隐藏状态的代码详解》文章介绍了如何在Flutter中使用路由观察者来监听应用进入前台或后台状态以及页面的显示和隐藏,并通过代码示例讲解的非常详细,需要的朋友可以参考下... flutter 可以监听 app 进入前台还是后台状态,也可以监听当http://www.cppcn