Upload image from Uri to Retrofit (S3 Signed url) not working

Viewed 116

Uploading to S3 signed URL's with a file as an origin works without problems, but trying to do it with an Uri I get from my ActivityResult is not working for me.

Here is what I try:

I'm using a InputStreamRequestBody class like described here: https://commonsware.com/blog/2020/07/05/multipart-upload-okttp-uri.html

class InputStreamRequestBody(
  private val contentType: MediaType,
  private val contentResolver: ContentResolver,
  private val uri: Uri
) : RequestBody() {
  override fun contentType() = contentType

  override fun contentLength(): Long = -1

  @Throws(IOException::class)
  override fun writeTo(sink: BufferedSink) {
    val input = contentResolver.openInputStream(uri)

    input?.use { sink.writeAll(it.source()) }
      ?: throw IOException("Could not open $uri")
  }
}

My Retrofit UploadAPI interface:

interface UploadAPI {

    @PUT
    suspend fun uploadFile(
        @Header("x-amz-acl") contentType: String,
        @Url uploadUrl: String,
        @Body file: RequestBody
    ): Response<Unit>


    companion object {
        const val BASE_URL = "https://....com"
    }
}

And here my Retrofit Singleton in AppModule:

@Provides
@Singleton
fun provideUploadApi(): UploadAPI { 

    return Retrofit.Builder()
        .baseUrl(UploadAPI.BASE_URL) 
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(UploadAPI::class.java)
}

And then calling the InputStreamRequestBody class with my Uri (in my repository) and calling the retrofit instance and upload function:

        val resolver = context.contentResolver
        val type = ("image/jpeg").toMediaType()
        val contentPart = InputStreamRequestBody(type, resolver, content) 

        uploadAPI.uploadFile(
                "public-read",
                mySignedUrl,
                contentPart
            )

this is what my logginInterceptor tells me:

2022-05-19 22:16:48.844 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: --> PUT https://app-content.ams3.digitaloceanspaces.com/Files/Test/profilbild.webp?Content-Type=image%2Fwebp&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=CENSORED-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read
2022-05-19 22:16:48.844 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: Content-Type: image/jpeg
2022-05-19 22:16:48.844 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: x-amz-acl: public-read
2022-05-19 22:16:48.896 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: --> END PUT (binary -1-byte body omitted)
2022-05-19 22:16:49.503 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: <-- 411 Length Required https://app-content.ams3.digitaloceanspaces.com/Files/Test/profilbild.webp?Content-Type=image%2Fwebp&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=CENSORED-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read (606ms)
2022-05-19 22:16:49.504 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: content-length: 239
2022-05-19 22:16:49.504 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: x-amz-request-id: tx000000000000004541b27-00622f61-20f93ecc-ams3c
2022-05-19 22:16:49.505 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: accept-ranges: bytes
2022-05-19 22:16:49.505 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: content-type: application/xml
2022-05-19 22:16:49.505 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: date: Thu, 19 May 2022 15:16:49 GMT
2022-05-19 22:16:49.505 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: cache-control: max-age=60
2022-05-19 22:16:49.506 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: strict-transport-security: max-age=15552000; includeSubDomains; preload
2022-05-19 22:16:49.506 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: connection: close
2022-05-19 22:16:49.506 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: <?xml version="1.0" encoding="UTF-8"?><Error><Code>MissingContentLength</Code><BucketName>app-content</BucketName><RequestId>tx00000000000000fffb27-0062865f61-20f93ecc-ams3c</RequestId><HostId>20f93ecc-ams3c-ams3-zg03</HostId></Error>
2022-05-19 22:16:49.507 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: <-- END HTTP (239-byte body)

I have the strong feeling that I cannot just pass the instance of InputStreamRequestBody as a requestBody eventhough this class inherrits from RequestBody.

0 Answers
Related