Android使用OkHttp上傳圖片的實例代碼
簡介
上傳圖片是一個APP的常見功能,可以是通過OOS上傳到阿里云,也可以直接上傳到Server后臺,OOS有提供相應(yīng)的SDK,此處忽略。下面通過OkHttp來實現(xiàn)圖片的上傳
代碼
直接上代碼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() }
//------基本參數(shù)----------
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() }
//------------------------
//不帶參數(shù)同步上傳文件
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
}
//不帶參數(shù)異步上傳文件
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()
}
})
}
//帶參數(shù)同步上傳文件
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
}
//帶參數(shù)異步上傳文件
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()
}
})
}
}
//------創(chuàng)建一個沒有帶參數(shù)的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)
}
//------創(chuàng)建一個帶參數(shù)的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)
}
//創(chuàng)建帶進度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)
}
}
}
}
}
//根據(jù)圖片大小簡單壓縮
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返回的數(shù)據(jù)獲取圖片路徑,
/*
{"code":200,"msg":"上傳成功","data":{"path":""}}
*/
fun getResponseToPath(response:String):String{
val dataJsonObj = JSONObject(response).get("data") as JSONObject
return dataJsonObj.get("path") as String
}
//回調(diào)方法
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
}
}
最后根據(jù)是否要帶參數(shù)、同步或異步調(diào)用其中對應(yīng)的方法可以了
syncUploadFile(xxx) asyncUploadFile(xxx) syncParamsUploadFile(xxx) asyncParamsUploadFile(xxx)
總結(jié)
首先根據(jù)是否要帶參數(shù)上傳,如果不帶參數(shù)上傳,直接創(chuàng)建RequestBody;如果帶參數(shù)上傳,創(chuàng)建MultipartBody.Builder(),然后把所有參數(shù)addFormDataPart進去,其中addFormDataPart方法有個RequestBody參數(shù)通過是否要監(jiān)聽進度創(chuàng)建,如果需要進度,需重寫RequestBody的writeTo()方法,如果不監(jiān)聽進度,直接創(chuàng)建RequestBody,最后builder.build()得到RequestBody
通過上步驟得到的RequestBody以及上傳圖片的Server路徑,可以配置出一個Request對象。
把Request對象通過.newCall(request)配置在OkHttpClient得到Call對象
最后Call調(diào)用同步.execute()或者異步.enqueue(callBack),在回調(diào)里面處理返回的數(shù)據(jù)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android使用post方式上傳圖片到服務(wù)器的方法
- Android實現(xiàn)本地上傳圖片并設(shè)置為圓形頭像
- Android Retrofit 2.0框架上傳圖片解決方案
- Android實現(xiàn)上傳圖片至java服務(wù)器
- android上傳圖片到PHP的過程詳解
- Android 開發(fā) 使用WebUploader解決安卓微信瀏覽器上傳圖片中遇到的bug
- Android基于OkHttp實現(xiàn)下載和上傳圖片
- Android 通過Base64上傳圖片到服務(wù)器實現(xiàn)實例
- Android異步上傳圖片到PHP服務(wù)器
- Android實現(xiàn)點擊圖片上傳SQLite數(shù)據(jù)庫
相關(guān)文章
Android 中TabLayout自定義選擇背景滑塊的實例代碼
TabLayout是Android 的Material Design包中的一個控件,可以和V4包中的ViewPager搭配產(chǎn)生一個聯(lián)動的效果。接下來通過本文給大家分享TabLayout自定義選擇背景滑塊的實例代碼,感興趣的朋友一起學(xué)習(xí)吧2016-10-10
android基礎(chǔ)總結(jié)篇之八:創(chuàng)建及調(diào)用自己的ContentProvider
這篇文章主要介紹了android基礎(chǔ)總結(jié)篇之八:創(chuàng)建及調(diào)用自己的ContentProvider,有興趣的可以了解一下。2016-11-11
Android自定義View實現(xiàn)帶4圓角或者2圓角的效果
這篇文章主要介紹了Android自定義View實現(xiàn)帶4圓角或者2圓角的效果,本文通過實例代碼截圖給大家展示的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03
Android編程四大組件之BroadcastReceiver(廣播接收者)用法實例
這篇文章主要介紹了Android編程四大組件之BroadcastReceiver(廣播接收者)用法,結(jié)合實例形式較為詳細的分析了BroadcastReceiver的功能.定義,用法及相關(guān)使用技巧,需要的朋友可以參考下2016-01-01
Android 如何獲取手機總內(nèi)存和可用內(nèi)存等信息
這篇文章主要介紹了Android系統(tǒng)檢測程序內(nèi)存占用各種方法,并對內(nèi)存信息的詳細介紹,需要的朋友可以參考下2016-07-07
Android 判斷當(dāng)前語言環(huán)境是否是中文環(huán)境
本文主要介紹了Android 判斷當(dāng)前語言環(huán)境是否是中文環(huán)境的方法。具有很好的參考價值。下面跟著小編一起來看下吧2017-04-04

