Android使用OkHttp上传图片的实例代码
简介
上传图片是一个APP的常见功能,可以是通过OOS上传到阿里云,也可以直接上传到Server后台,OOS有提供相应的SDK,此处忽略。下面通过OkHttp来实现图片的上传
代码
直接上代码UploadFileHelper.kt
objectUploadFileHelper{
//--------ContentType
privatevalMEDIA_OBJECT_STREAM=MediaType.parse("multipart/form-data")
//--------上传延时时间
privatevalWRITE_TIME_OUT:Long=50
privatevalmOkHttpClientbylazy{OkHttpClient()}
//------基本参数----------
valversion=AppConstant.API_VERSION
valplatform=AppConstant.API_PLATFORM
valmethodName=AppConstant.API_UPLOADFILE_METHOD
valtoken=ignoreException(""){UserModel.token()}
valuserId=ignoreException(0){UserModel.id()}
//------------------------
//不带参数同步上传文件
funsyncUploadFile(actionUrl:String="",file:File,maxW:Int=256,maxH:Int=256):String?{
valuploadFile=optionFileSize(file,maxW,maxH,null)
if(uploadFile!=null){
valresponse=createNoParamsOkHttpCall(actionUrl,uploadFile).execute()
if(uploadFile.exists())
uploadFile.delete()
returngetResponseToPath(response.body()!!.string())
}
returnnull
}
//不带参数异步上传文件
funasyncUploadFile(actionUrl:String="",file:File,maxW:Int=256,maxH:Int=256,
uploadCallBackListener:UploadCallBackListener?=null){
valuploadFile=optionFileSize(file,maxW,maxH,uploadCallBackListener)
if(uploadFile!=null)
createNoParamsOkHttpCall(actionUrl,uploadFile).enqueue(object:Callback{
overridefunonFailure(c:Call,e:IOException){
uploadCallBackListener?.onUploadFailure(e.toString())
}
overridefunonResponse(c:Call,response:Response){
if(uploadFile.exists())
uploadFile.delete()
uploadCallBackListener?.onUploadSuccess(getResponseToPath(response.body()!!.string()))
response.body()!!.close()
}
})
}
//带参数同步上传文件
funsyncParamsUploadFile(actionUrl:String="",file:File,params:HashMap,
maxW:Int=256,maxH:Int=256):String?{
valuploadFile=optionFileSize(file,maxW,maxH,null)
if(uploadFile!=null){
params.put("filename",uploadFile)
valresponse=createParamsOkHttpCall(actionUrl,params,null,false).execute()
if(uploadFile.exists())
uploadFile.delete()
returngetResponseToPath(response.body()!!.string())
}
returnnull
}
//带参数异步上传文件
funasyncParamsUploadFile(actionUrl:String="",file:File,params:HashMap,maxW:Int=256,maxH:Int=256,
uploadCallBackListener:UploadCallBackListener?=null,isProgress:Boolean=true){
valuploadFile=optionFileSize(file,maxW,maxH,uploadCallBackListener)
if(uploadFile!=null){
params.put("filename",uploadFile)
createParamsOkHttpCall(actionUrl,params,uploadCallBackListener,isProgress).enqueue(object:Callback{
overridefunonFailure(c:Call,e:IOException){
uploadCallBackListener?.onUploadFailure(e.toString())
}
overridefunonResponse(c:Call,response:Response){
if(uploadFile.exists())
uploadFile.delete()
uploadCallBackListener?.onUploadSuccess(getResponseToPath(response.body()!!.string()))
response.body()!!.close()
}
})
}
}
//------创建一个没有带参数的Call
funcreateNoParamsOkHttpCall(actionUrl:String,file:File):Call{
valrequestUrl="${AppConstant.HOST}/$actionUrl"
valrequestBody=RequestBody.create(MEDIA_OBJECT_STREAM,file)
valrequest=Request.Builder().url(requestUrl).post(requestBody).build()
returnmOkHttpClient.newBuilder().writeTimeout(WRITE_TIME_OUT,TimeUnit.SECONDS).build().newCall(request)
}
//------创建一个带参数的Call
funcreateParamsOkHttpCall(actionUrl:String,params:Map,
uploadCallBackListener:UploadCallBackListener?=null,
isProgress:Boolean=true):Call{
//-----AppConstant.HOST上传图片的Server的BASE_URLhttp://xxx.com
valrequestUrl="${AppConstant.HOST}/$actionUrl"
valbuilder=MultipartBody.Builder()
builder.setType(MultipartBody.FORM)
valnewParams=mutableMapOf(
"version"toversion,
"platform"toplatform,
"methodName"tomethodName,
"token"totoken,
"user_id"touserId)
newParams.putAll(params)
newParams.forEach(action={
if(it.valueisFile){
builder.addFormDataPart(it.key,(it.valueasFile).name,
if(isProgress)createProgressRequestBody(MEDIA_OBJECT_STREAM!!,(it.valueasFile),uploadCallBackListener)
elseRequestBody.create(null,(it.valueasFile)))
}else{
builder.addFormDataPart(it.key,it.value.toString())
}
})
valbody=builder.build()
valrequest=Request.Builder().url(requestUrl).post(body).build()
returnmOkHttpClient.newBuilder().writeTimeout(WRITE_TIME_OUT,TimeUnit.SECONDS).build().newCall(request)
}
//创建带进度RequestBody
funcreateProgressRequestBody(contentType:MediaType,file:File,
uploadCallBackListener:UploadCallBackListener?=null):RequestBody{
returnobject:RequestBody(){
overridefuncontentType():MediaType=contentType
overridefuncontentLength()=file.length()
overridefunwriteTo(sink:BufferedSink){
ignoreException{
valsource=Okio.source(file)
valbuf=Buffer()
valremaining=contentLength()
varcurrent:Long=0
varreadCount:Long=source.read(buf,2048)
while(readCount!=-1L){
sink.write(buf,readCount)
current+=readCount
uploadCallBackListener?.onUploadProgress(current,remaining)
readCount=source.read(buf,2048)
}
}
}
}
}
//根据图片大小简单压缩
funoptionFileSize(file:File,maxW:Int,maxH:Int,uploadCallBackListener:UploadCallBackListener?):File?{
try{
valuploadFile=File(AppBridge.AppContext().externalCacheDir,file.hashCode().toString())
ImageUtils.resize(file,maxW,maxH,uploadFile)
returnuploadFile
}catch(e:Exception){
uploadCallBackListener?.onUploadFailure("压缩图片失败")
returnnull
}
}
//解析Server返回的数据获取图片路径,
/*
{"code":200,"msg":"上传成功","data":{"path":""}}
*/
fungetResponseToPath(response:String):String{
valdataJsonObj=JSONObject(response).get("data")asJSONObject
returndataJsonObj.get("path")asString
}
//回调方法
interfaceUploadCallBackListener{
funonUploadFailure(error:String)
funonUploadProgress(currentSize:Long,totalSize:Long)
funonUploadSuccess(path:String)
}
}
inlinefunignoreException(def:T,f:()->T):T{ try{ returnf() }catch(e:Exception){ Timber.e(e,"") returndef } }
最后根据是否要带参数、同步或异步调用其中对应的方法可以了
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),在回调里面处理返回的数据。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。