Android Retrofit2和Kotlin结合上传文件

现在Retrofit2和RxJava2是很流行的框架,可能是我太闭塞的缘故,竟然没有用过这样的框架,请原谅我以前都是在用xUtils3
今天就来说一下Retrofit2和Kotlin结合上传文件
1、首先集成工具
(1)Kotlin就不用说了,Android Studio 3.0 以后自身就有
(2)Retrofit2集成 在项目文件build.gradle 里添加

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.android.support:design:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
}

2、
(1)编写一个KtvApiService接口

 /**
 * 作者:Galen on 2017/12/16 13:56
 * 邮箱:[email protected]
 */
interface KtvApiService {
@Multipart
@POST(FACE_DETECT)
fun detectFace(
        @Part("api_key") api_key: RequestBody,
        @Part("api_secret") api_secret: RequestBody ,
        @Part("return_attributes") return_attributes: RequestBody ,
        @Part part: MultipartBody.Part ): Call
@FormUrlEncoded
@POST(FACE_SET_GETDETAIL)
fun getFaceSetDetail(@Field("api_key") api_key: String,
                     @Field("api_secret") api_secret: String,
                     @Field("outer_id") outer_id: String):Call
}

(2)、编写请求地址配置Constants(是一个静态的类)

/**
 * 作者:Galen on 2017/12/16 13:58
 * 邮箱:[email protected]
 */
object Constants {
val LOCAL_SAVE_FACE_IMAGE = Environment.getExternalStorageDirectory().absolutePath + "/face.jpg"
val FACE_BASE_URL = "https://api-cn.faceplusplus.com/facepp/v3/"
const val FACE_DETECT = "detect"
val FACE_FEATURE = "facequality,blur"
val FACE_COMPARE = FACE_BASE_URL + "compare"
val FACE_SEARCH = FACE_BASE_URL + "search"
val FACE_SET = FACE_BASE_URL + "faceset/"
val FACE_SET_CREATE = FACE_SET + "create"
val FACE_SET_ADDFACE = FACE_SET + "addface"
val FACE_SET_REMOVEFACE = FACE_SET + "removeface"
val FACE_SET_UPDATE = FACE_SET + "update"
const val FACE_SET_GETDETAIL ="faceset/getdetail"
val FACE_SET_DELETE = FACE_SET + "delete"
val FACE_SET_GETFACESETS = FACE_SET + "getfacesets"
}

(3)编写返回值 DetectFaceResult(我直接用的GsonFormat转的bean文件)

/**
 * 作者:Galen on 2017/12/13 19:31
 * 邮箱:[email protected]
 */

class DetectFaceResult {

/**
 * image_id : rMqAJcCPIa/et7wAJ4BLpw==
 * request_id : 1513164138,f175169b-58c5-43af-ba58-d9150cc72f5c
 * time_used : 404
 * faces : [{"attributes":{"facequality":{"threshold":70.1,"value":74.748},"blur":{"blurness":{"threshold":50,"value":21.626},"motionblur":{"threshold":50,"value":21.626},"gaussianblur":{"threshold":50,"value":21.626}}},"face_rectangle":{"width":338,"top":87,"left":182,"height":338},"face_token":"5e43726aa72d35e5e78040c6b819dfb1"}]
 */

var image_id: String? = null
var request_id: String? = null
var time_used: Int = 0
var faces: List? = null

class FacesBean {
    /**
     * attributes : {"facequality":{"threshold":70.1,"value":74.748},"blur":{"blurness":{"threshold":50,"value":21.626},"motionblur":{"threshold":50,"value":21.626},"gaussianblur":{"threshold":50,"value":21.626}}}
     * face_rectangle : {"width":338,"top":87,"left":182,"height":338}
     * face_token : 5e43726aa72d35e5e78040c6b819dfb1
     */

    var attributes: AttributesBean? = null
    var face_rectangle: FaceRectangleBean? = null
    var face_token: String? = null

    class AttributesBean {
        /**
         * facequality : {"threshold":70.1,"value":74.748}
         * blur : {"blurness":{"threshold":50,"value":21.626},"motionblur":{"threshold":50,"value":21.626},"gaussianblur":{"threshold":50,"value":21.626}}
         */

        var facequality: FacequalityBean? = null
        var blur: BlurBean? = null

        class FacequalityBean {
            /**
             * threshold : 70.1
             * value : 74.748
             */

            var threshold: Double = 0.toDouble()
            var value: Double = 0.toDouble()
        }

        class BlurBean {
            /**
             * blurness : {"threshold":50,"value":21.626}
             * motionblur : {"threshold":50,"value":21.626}
             * gaussianblur : {"threshold":50,"value":21.626}
             */

            var blurness: BlurnessBean? = null
            var motionblur: MotionblurBean? = null
            var gaussianblur: GaussianblurBean? = null

            class BlurnessBean {
                /**
                 * threshold : 50.0
                 * value : 21.626
                 */

                var threshold: Double = 0.toDouble()
                var value: Double = 0.toDouble()
            }

            class MotionblurBean {
                /**
                 * threshold : 50.0
                 * value : 21.626
                 */

                var threshold: Double = 0.toDouble()
                var value: Double = 0.toDouble()
            }

            class GaussianblurBean {
                /**
                 * threshold : 50.0
                 * value : 21.626
                 */

                var threshold: Double = 0.toDouble()
                var value: Double = 0.toDouble()
            }
        }
    }

    class FaceRectangleBean {
        /**
         * width : 338
         * top : 87
         * left : 182
         * height : 338
         */

        var width: Int = 0
        var top: Int = 0
        var left: Int = 0
        var height: Int = 0
    }
}
}

(4)调用

   fun faceDetect() {
  //创建Okhttp
    val builder = OkHttpClient.Builder()
  //添加日志拦截器(自定义日志拦截器)也可以不添加
  //builder.addInterceptor(LoggingInterceptor())
    val client = builder.build() 
    val retrofit = Retrofit.Builder()
    .client(client)
    .baseUrl(FACE_BASE_URL)
    .addConverterFactory(GsonConverterFactory.create())
    .build()
           
    val service = retrofit.create(KtvApiService::class.java)
    val file = File(LOCAL_SAVE_FACE_IMAGE)
    val photoRequestBody = RequestBody.create(MediaType.parse("image/jpg"), file)
    val photoPart = MultipartBody.Part.createFormData("image_file", file.name, photoRequestBody)
    val api_key = RequestBody.create(MediaType.parse("text/plain"), API_KEY)
    val api_secret = RequestBody.create(MediaType.parse("text/plain"), API_SECRET)
    val return_attributes = RequestBody.create(MediaType.parse("text/plain"), FACE_FEATURE)
    if (file.exists()) {
        val repos = service.detectFace(api_key, api_secret, return_attributes, photoPart)
        repos.enqueue(object : Callback {
            override fun onResponse(call: Call?, response: Response?) {
                if (response != null) {
                    Log.e("ScanActivity 成功", response.body().toString())
                }

            }

            override fun onFailure(call: Call?, t: Throwable?) {
                Log.e("ScanActivity  失败", t.toString())

            }
        })

    }
}

重点内容
上传图片要携带参数时必须要以这样的格式

     @Multipart
@POST(FACE_DETECT)
fun detectFace(
        @Part("api_key") api_key: RequestBody,
        @Part("api_secret") api_secret: RequestBody ,
        @Part("return_attributes") return_attributes: RequestBody ,
        @Part part: MultipartBody.Part ): Call

而不是

@Multipart
@POST(FACE_DETECT)
fun detectFace(
        @Part("api_key") api_key: String,
        @Part("api_secret") api_secret: String,
        @Part("return_attributes") return_attributes: String,
        @Part part: MultipartBody.Part ): Call

这样上传是错误的
调用的时候
携带的参数应该这样写
上传照片的参数应该这样

    val photoRequestBody = RequestBody.create(MediaType.parse("image/jpg"), file)
    val photoPart = MultipartBody.Part.createFormData("image_file", file.name, photoRequestBody)

其他参数

val api_key = RequestBody.create(MediaType.parse("text/plain"), API_KEY)
val api_secret = RequestBody.create(MediaType.parse("text/plain"), API_SECRET)
val return_attributes = RequestBody.create(MediaType.parse("text/plain"), FACE_FEATURE)

到此完工
本人第一次在写文章,请多多关照,如需帮助,求留言,也请大家多多指教

你可能感兴趣的:(Android Retrofit2和Kotlin结合上传文件)