阿里云OSS图片上传实践

目前公司里的项目用到的文件管理服务都是阿里云OSS,下面介绍下Android端上传图片到阿里云OSS的具体实践。

阿里云OSS

1.阿里云OSS 移动应用方案请见官方文档基于OSS的移动开发
2.阿里云OSS Android SDK的介绍、安装、使用请见官方文档

上传图片流程

  1. 从APP服务端获取Token
  2. 通过Token上传图片到阿里云OSS
  3. 成功后通知APP服务端。

简单图示如下(省略了APP服务端和阿里云OSS之间的交互流程)
上传图片流程

代码实现

上面流程中实现了三次网络通信的操作,在实践中,使用了RxJava的链式调用,简洁、明了。

APP服务端的接口

  1. 请求Token的接口
  2. 通知APP服务端上传成功的接口
interface AppServiceApi {
    // ...

    @GET("aliyun/sts")
    fun getAliOSSSTS(@Header("X-Authorization") token: String,
                     @Query("right") right: String,
                     @Query("prod") prod: String
    ): Flowable>

    @PUT("users/v1/avatar")
    fun notifyAvatarUpdate(@Header("X-Authorization") token: String
    ): Flowable>

    // ...
}

object AppService {
    private val API_BASE_URL = BuildConfig.SERVICE_PLATFORM
    fun api(): AppServiceApi {
        val retrofit = Retrofit.Builder()
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(API_BASE_URL)
                .build()
        return retrofit.create(AppServiceApi::class.java)
    }
}

阿里云OSS的接口
上传图片的接口。其中将OSS SDK的方法改造成RxJava样式,便于链式调用。

object AliOSSService {
    private val clientConfiguration = config()

    private fun config(): ClientConfiguration {
        val conf = ClientConfiguration()
        conf.connectionTimeout = 15 * 1000 // 连接超时,默认15秒
        conf.socketTimeout = 15 * 1000 // socket超时,默认15秒
        conf.maxConcurrentRequest = 5 // 最大并发请求数,默认5个
        conf.maxErrorRetry = 2 // 失败后最大重试次数,默认2次
        return conf
    }

    fun uploadFile(context: Context, stsModel: AliOSSSTSModel, fileData: ByteArray): Flowable> {
        val credentialProvider = OSSStsTokenCredentialProvider(
                stsModel.credentials.accessKeyId,
                stsModel.credentials.accessKeySecret,
                stsModel.credentials.securityToken)
        val oss = OSSClient(context, stsModel.endpoint, credentialProvider, clientConfiguration)
        val put = PutObjectRequest(stsModel.bucket, stsModel.objectKey, fileData)
        return Flowable.create({ subscriber ->
            oss.asyncPutObject(put, object : OSSCompletedCallback {
                override fun onSuccess(request: PutObjectRequest?, result: PutObjectResult?) {
                    subscriber.onNext(ApiResponse(ApiCode.SUCCESS.code, true, "success"))
                    subscriber.onComplete()
                }

                override fun onFailure(request: PutObjectRequest?, clientException: ClientException?, serviceException: ServiceException?) {
                    subscriber.onError(ApiException(
                            code = if (serviceException == null) "10" else serviceException.errorCode,
                            message = serviceException?.rawMessage
                    ))
                }
            })
        }, BackpressureStrategy.LATEST)
    }
}

将三个接口封装成一个,便于调用

object NetApi {
   // avatar
    fun uploadAvatar(context: Context, avatarData: ByteArray): Flowable> {
        return AppService.api()
                .getAliOSSSTS(token(),"WRITE", "OSS") // 获取Token
                .flatMap { response ->
                    AliOSSService.uploadFile(context, response.data!!, avatarData)
                } // 上传图片
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .flatMap {
                    AppService.api().notifyAvatarUpdate(token()) // 通知服务端
                }
                .compose(apply()) // 线程切换等后续处理
    }
}

在上传图片的Activity中调用接口即可

   private fun uploadAvatarWithToken(avatar: Drawable):Disposable {
        val data = ImageUtils.drawable2Bytes(avatar, Bitmap.CompressFormat.PNG)
        return NetApi.uploadAvatar(this, data)
                .subscribe({
                    Util.toast().showShort(R.string.avatar_upload_success_prompt)
                    finish()
                }, { t->
                    if (!NetErrorHelper.handleAuth(t, this)) {
                        Util.toast().showShort(R.string.avatar_upload_fail_prompt)
                    }
                })
    }

你可能感兴趣的:(阿里云OSS图片上传实践)