如何在 kotlin 中将二进制图像上传到 AWS 预签名 url?

问题描述 投票:0回答:2

我正在尝试在 s3 presignedURL 上上传图像(在流中)。然而,它给了我 403。通过 POSTMAN 上传相同的文件可以工作,但通过改造完成时则不行。我错过了什么?

以下是我的代码:-

val stream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream)//bitmap is the bitmap of the image
val byteArray = stream.toByteArray()
val encodedImage = Base64.encodeToString(byteArray, Base64.DEFAULT)
val requestBody : RequestBody = encodedImage.toRequestBody()// for base64 format              


val url = 'https://s3.presigned_url.com'
val baseUrl = url.split(".com").toTypedArray()[0] + ".com"
var queryUrl: String? = url.split(".com").toTypedArray()[1]

val client = OkHttpClient.Builder().build()

val retrofit_image_upload: Retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    .addConverterFactory(GsonConverterFactory.create())
    .client(client)
    .build()

var request1 = retrofit_image_upload.create(Api::class.java)
try {
    request1.upload(
        url,
        fileSize,//size of the image
        requestBody,
    ).enqueue(
        object : retrofit2.Callback<Void> {
            override fun onResponse(call: Call<Void>, response: Response<Void>) {
                println(response.code().toString())
            }
            override fun onFailure(call: Call<Void>, t: Throwable) {
                println(t.toString())
            }
        }
    )
} catch (e: IOException) {
    e.printStackTrace()
}

上传方法如下:-

@PUT
fun upload(
    @Url url: String,
    @Header("content-length") contentlength: Int,
    @Body image: RequestBody,
): Call<Void>

也将请求体转换为流,但结果是一样的。

我参考了以下文章,但仍然无法解决。

Android HttpURLConnection PUT 到 Amazon AWS S3 403 错误

PUT 上传文件到 AWS S3 预签名 url Retrofit2 Android

https://gutier.io/post/android-upload-file-to-aws-s3-bucket-with-retrofit2/

android amazon-web-services kotlin retrofit pre-signed-url
2个回答
0
投票

使用http url连接

val connection: HttpURLConnection = URL(presignedUrl).openConnection() as HttpURLConnection
connection.doOutput = true`
connection.setRequestProperty("Content-Type", "image/png")
connection.requestMethod = "PUT"
val out =  DataOutputStream(connection.outputStream)
val fileBytes = file.readBytes()
out.write(fileBytes)
out.close()
if (connection.responseCode == 200){
   TODO
}`

0
投票

我最近遇到了类似的情况,经过一番挣扎,我找到了解决方案。如果您使用预签名 URL 以二进制形式将图像上传到 S3,则需要使用 Retrofit 传递 @Query 或 @QueryMap 中的所有查询参数。

@PUT
fun uploadFile(
    @Url url: String,
    @Body file: RequestBody,
    @QueryMap param: Map<String, String>

): Call<Unit>

您可以使用此功能来创建QueryMap

fun String.createQueryMap(): Map<String, String> {
val queryMap = mutableMapOf<String, String>()

val parts = split("?")
if (parts.size > 1) {
    val queryString = parts[1]
    val queryParams = queryString.split("&")
    for (queryParam in queryParams) {
        val keyValue = queryParam.split("=")
        if (keyValue.size == 2) {
            val key = keyValue[0]
            val value = keyValue[1]
            queryMap[key] = value
        }
    }

}

return queryMap

}

让我知道您在此之后遇到任何问题

© www.soinside.com 2019 - 2024. All rights reserved.