Android使用OkHttp上传图片的实例代码

发布时间 - 2026-01-11 02:08:16    点击率:

简介

上传图片是一个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),在回调里面处理返回的数据。

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


# OkHttp上传图片  # 使用okhttp上传图片  # okhttp  # 上传图片文件  # Android使用post方式上传图片到服务器的方法  # Android实现本地上传图片并设置为圆形头像  # Android Retrofit 2.0框架上传图片解决方案  # Android实现上传图片至java服务器  # android上传图片到PHP的过程详解  # Android 开发 使用WebUploader解决安卓微信浏览器上传图片中遇到的bug  # Android基于OkHttp实现下载和上传图片  # Android 通过Base64上传图片到服务器实现实例  # Android异步上传图片到PHP服务器  # Android实现点击图片上传SQLite数据库  # 上传  # 上传文件  # 不带  # 上传图片  # 要带  # 创建一个  # 回调  # 是一个  # 有个  # 可以直接  # 重写  # 来实现  # 大家多多  # uploadFile  # maxH  # optionFileSize  # createNoParamsOkHttpCall  # execute  # null  # response 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何使用.env文件管理环境变量?(最佳实践)  详解CentOS6.5 安装 MySQL5.1.71的方法  javascript基于原型链的继承及call和apply函数用法分析  Laravel Telescope怎么调试_使用Laravel Telescope进行应用监控与调试  Laravel Blade模板引擎语法_Laravel Blade布局继承用法  网站制作软件有哪些,制图软件有哪些?  佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】  javascript事件捕获机制【深入分析IE和DOM中的事件模型】  Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层  Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】  Laravel怎么为数据库表字段添加索引以优化查询  原生JS实现图片轮播切换效果  Laravel如何发送系统通知?(Notification渠道示例)  javascript中的try catch异常捕获机制用法分析  Laravel项目怎么部署到Linux_Laravel Nginx配置详解  Python结构化数据采集_字段抽取解析【教程】  如何获取PHP WAP自助建站系统源码?  Laravel如何使用Blade组件和插槽?(Component代码示例)  Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权  Linux后台任务运行方法_nohup与&使用技巧【技巧】  猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?  Laravel队列由Redis驱动怎么配置_Laravel Redis队列使用教程  开心动漫网站制作软件下载,十分开心动画为何停播?  JavaScript如何实现类型判断_typeof和instanceof有什么区别  如何制作一个表白网站视频,关于勇敢表白的小标题?  android nfc常用标签读取总结  JavaScript常见的五种数组去重的方式  如何在Windows环境下新建FTP站点并设置权限?  如何在宝塔面板中创建新站点?  HTML 中如何正确使用模板变量为元素的 name 属性赋值  Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?  利用python获取某年中每个月的第一天和最后一天  JavaScript如何实现错误处理_try...catch如何捕获异常?  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  bootstrap日历插件datetimepicker使用方法  Laravel如何构建RESTful API_Laravel标准化API接口开发指南  php打包exe后无法访问网络共享_共享权限设置方法【教程】  小米17系列还有一款新机?主打6.9英寸大直屏和旗舰级影像  香港服务器建站指南:外贸独立站搭建与跨境电商配置流程  Laravel怎么进行数据库回滚_Laravel Migration数据库版本控制与回滚操作  Laravel Fortify是什么,和Jetstream有什么关系  个人摄影网站制作流程,摄影爱好者都去什么网站?  Laravel如何与Docker(Sail)协同开发?(环境搭建教程)  如何快速查询网站的真实建站时间?  长沙企业网站制作哪家好,长沙水业集团官方网站?  如何在香港免费服务器上快速搭建网站?  Laravel如何处理和验证JSON类型的数据库字段  独立制作一个网站多少钱,建立网站需要花多少钱?