安卓阿里oss简易的文件上传

记录一次使用阿里oss的文件上传功能,简易版
配合okhttp3实现,没使用阿里配套的sdk

文件上传有PUT和POST,这里使用的是PUT

依赖

implementation("com.squareup.okhttp3:okhttp:4.8.0")

生成GMT格式时间

1
2
3
4
5
6
private fun getGMTDate(): String {
val cd = Calendar.getInstance()
val sdf = SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US)
sdf.timeZone = TimeZone.getTimeZone("GMT")
return sdf.format(cd.time)
}

Hmac-Sha1 加密

1
2
3
4
5
6
7
8
private fun sha1(string: String, key: String): ByteArray {
val algorithm = "HmacSHA1"
val data = string.toByteArray(Charsets.UTF_8)
val secretKeySpec = SecretKeySpec(key.toByteArray(Charsets.UTF_8), algorithm)
val mac = Mac.getInstance(algorithm)
mac.init(secretKeySpec)
return mac.doFinal(data)
}

Base64 加密

1
2
3
private fun base64(byteArray: ByteArray): String {
return Base64.getEncoder().encodeToString(byteArray)
}

简易的PUT 上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
private const val BaseUrl = "http://BucketName.oss-cn-shenzhen.aliyuncs.com"
private const val BucketName = "test"
private const val AccessKeyID = "*****"
private const val AccessKeySecret = "*****"

object Oss{
/**
* @Description Authorization 签名
* @author lecoler
* @param date:String GMT格式的时间
* @param key:String 上传Object的名称
* @return String 签名
**/
private fun sign(date: String, key: String): String {
val value = "PUT\n\napplication/octet-stream\n$date\n/$BucketName/$key"
return base64(sha1(value, AccessKeySecret))
}

/**
* @Description 上传文件
* @author lecoler
* @param file:File 需要上传的文体
* @param key:String 上传Object的名称。
* 如果名称包含路径,例如a/b/c/b.jpg,则OSS会自动创建相应的文件夹。
**/
fun upload(file: File, key: String) {
val GMT = getGMTDate()
val fileBody = RequestBody.create("application/octet-stream".toMediaTypeOrNull(), file)

// 新建请求
val client = OkHttpClient()
client.newCall(
Request.Builder()
.url("$BaseUrl/$key")
.method("PUT", fileBody)
.addHeader("Date", GMT)
.addHeader("Authorization", "OSS $AccessKeyID:${sign(GMT, key)}")
.build()
)
// 发送请求
.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("OSS","OSS PutObject 上传报错:${e.message}")
}

override fun onResponse(call: Call, response: Response) {
Log.i("OSS",response.toString())
}
})
}
}

DOME

1
2
val file = File("abc.txt")
Oss.upload(file,"Android/20200916/abc.txt")