神刀安全网

阿里云OSS图片上传实践

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

阿里云OSS

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

上传图片流程

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

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

阿里云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<ApiResponse<AliOSSSTSModel>>      @PUT("users/v1/avatar")     fun notifyAvatarUpdate(@Header("X-Authorization") token: String     ): Flowable<ApiResponse<Boolean?>>      // ... }  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<ApiResponse<Boolean?>> {         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<PutObjectRequest, PutObjectResult> {                 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<ApiResponse<Boolean?>> {         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图片上传实践

分享到:更多 ()