欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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),在回调里面处理返回的数据。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。