Android使用OkHttp上传图片的实例代码
程序员文章站
2023-10-27 17:54:10
简介
上传图片是一个app的常见功能,可以是通过oos上传到阿里云,也可以直接上传到server后台,oos有提供相应的sdk,此处忽略。下面通过okhttp来实现图片的...
简介
上传图片是一个app的常见功能,可以是通过oos上传到阿里云,也可以直接上传到server后台,oos有提供相应的sdk,此处忽略。下面通过okhttp来实现图片的上传
代码
直接上代码uploadfilehelper.kt
object uploadfilehelper { //--------contenttype private val media_object_stream = mediatype.parse("multipart/form-data") //--------上传延时时间 private val write_time_out:long = 50 private val mokhttpclient by lazy { okhttpclient() } //------基本参数---------- val version = appconstant.api_version val platform = appconstant.api_platform val methodname = appconstant.api_uploadfile_method val token = ignoreexception("") { usermodel.token() } val userid = ignoreexception(0) { usermodel.id() } //------------------------ //不带参数同步上传文件 fun syncuploadfile(actionurl: string = "",file: file,maxw: int = 256,maxh: int = 256):string?{ val uploadfile = optionfilesize(file,maxw,maxh,null) if(uploadfile!=null){ val response = createnoparamsokhttpcall(actionurl,uploadfile).execute() if(uploadfile.exists()) uploadfile.delete() return getresponsetopath(response.body()!!.string()) } return null } //不带参数异步上传文件 fun asyncuploadfile(actionurl:string = "", file: file,maxw: int = 256,maxh: int = 256, uploadcallbacklistener: uploadcallbacklistener? = null){ val uploadfile = optionfilesize(file,maxw,maxh,uploadcallbacklistener) if(uploadfile!=null) createnoparamsokhttpcall(actionurl,uploadfile).enqueue(object: callback{ override fun onfailure(c: call, e: ioexception) { uploadcallbacklistener?.onuploadfailure(e.tostring()) } override fun onresponse(c: call, response: response) { if(uploadfile.exists()) uploadfile.delete() uploadcallbacklistener?.onuploadsuccess(getresponsetopath(response.body()!!.string())) response.body()!!.close() } }) } //带参数同步上传文件 fun syncparamsuploadfile(actionurl: string= "",file: file,params:hashmap<string,any>, maxw: int = 256,maxh: int = 256):string?{ val uploadfile = optionfilesize(file,maxw,maxh,null) if(uploadfile!=null){ params.put("filename",uploadfile) val response = createparamsokhttpcall(actionurl,params,null,false).execute() if(uploadfile.exists()) uploadfile.delete() return getresponsetopath(response.body()!!.string()) } return null } //带参数异步上传文件 fun asyncparamsuploadfile(actionurl: string= "",file: file,params:hashmap<string,any>,maxw: int = 256,maxh: int = 256, uploadcallbacklistener: uploadcallbacklistener? = null, isprogress:boolean = true){ val uploadfile = optionfilesize(file,maxw,maxh,uploadcallbacklistener) if(uploadfile!=null){ params.put("filename",uploadfile) createparamsokhttpcall(actionurl,params,uploadcallbacklistener,isprogress).enqueue(object :callback{ override fun onfailure(c: call, e: ioexception) { uploadcallbacklistener?.onuploadfailure(e.tostring()) } override fun onresponse(c: call, response: response) { if(uploadfile.exists()) uploadfile.delete() uploadcallbacklistener?.onuploadsuccess(getresponsetopath(response.body()!!.string())) response.body()!!.close() } }) } } //------创建一个没有带参数的call fun createnoparamsokhttpcall(actionurl: string,file: file):call{ val requesturl = "${appconstant.host}/$actionurl" val requestbody = requestbody.create(media_object_stream,file) val request = request.builder().url(requesturl).post(requestbody).build() return mokhttpclient.newbuilder().writetimeout(write_time_out,timeunit.seconds).build().newcall(request) } //------创建一个带参数的call fun createparamsokhttpcall(actionurl: string,params:map<string,any>, uploadcallbacklistener: uploadcallbacklistener? = null, isprogress:boolean = true):call{ //-----appconstant.host 上传图片的server的base_url http://xxx.com val requesturl = "${appconstant.host}/$actionurl" val builder = multipartbody.builder() builder.settype(multipartbody.form) val newparams = mutablemapof( "version" to version, "platform" to platform, "methodname" to methodname, "token" to token, "user_id" to userid) newparams.putall(params) newparams.foreach( action = { if(it.value is file){ builder.addformdatapart(it.key, (it.value as file).name, if(isprogress) createprogressrequestbody(media_object_stream!!,(it.value as file),uploadcallbacklistener) else requestbody.create(null, (it.value as file))) }else{ builder.addformdatapart(it.key,it.value.tostring()) } }) val body = builder.build() val request = request.builder().url(requesturl).post(body).build() return mokhttpclient.newbuilder().writetimeout(write_time_out,timeunit.seconds).build().newcall(request) } //创建带进度requestbody fun createprogressrequestbody(contenttype:mediatype,file:file, uploadcallbacklistener: uploadcallbacklistener? = null):requestbody{ return object:requestbody(){ override fun contenttype(): mediatype = contenttype override fun contentlength() = file.length() override fun writeto(sink: bufferedsink) { ignoreexception { val source = okio.source(file) val buf = buffer() val remaining = contentlength() var current: long = 0 var readcount: long = source.read(buf, 2048) while (readcount != -1l) { sink.write(buf, readcount) current += readcount uploadcallbacklistener?.onuploadprogress(current,remaining) readcount = source.read(buf, 2048) } } } } } //根据图片大小简单压缩 fun optionfilesize(file: file,maxw:int,maxh:int,uploadcallbacklistener: uploadcallbacklistener?):file?{ try { val uploadfile = file(appbridge.appcontext().externalcachedir, file.hashcode().tostring()) imageutils.resize(file, maxw, maxh, uploadfile) return uploadfile } catch (e: exception) { uploadcallbacklistener?.onuploadfailure("压缩图片失败") return null } } //解析server返回的数据获取图片路径, /* {"code":200,"msg":"上传成功","data":{"path":""}} */ fun getresponsetopath(response:string):string{ val datajsonobj = jsonobject(response).get("data") as jsonobject return datajsonobj.get("path") as string } //回调方法 interface uploadcallbacklistener{ fun onuploadfailure(error:string) fun onuploadprogress(currentsize:long,totalsize:long) fun onuploadsuccess(path:string) } }
inline fun <t> ignoreexception(def: t, f: () -> t): t { try { return f() } catch(e: exception) { timber.e(e, "") return def } }
最后根据是否要带参数、同步或异步调用其中对应的方法可以了
syncuploadfile(xxx) asyncuploadfile(xxx) syncparamsuploadfile(xxx) asyncparamsuploadfile(xxx)
总结
首先根据是否要带参数上传,如果不带参数上传,直接创建requestbody;如果带参数上传,创建multipartbody.builder(),然后把所有参数addformdatapart进去,其中addformdatapart方法有个requestbody参数通过是否要监听进度创建,如果需要进度,需重写requestbody的writeto()方法,如果不监听进度,直接创建requestbody,最后builder.build()得到requestbody
通过上步骤得到的requestbody以及上传图片的server路径,可以配置出一个request对象。
把request对象通过.newcall(request)配置在okhttpclient得到call对象
最后call调用同步.execute()或者异步.enqueue(callback),在回调里面处理返回的数据。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。