0

I am able to get the ANDROID_GET_CONTENT source and load it. Only photos over 2 MB won't load. While I can upload photos up to 2MB without issue, I can't upload to higher size. My code and logs are as follows.

    @Multipart
    @POST("v1/product...")
    suspend fun productImage(
        @Part files: MultipartBody.Part,
        @Part("imageKey") imageKey: String
    ): ImageResponse

fun Uri.progressRequestBody(
    context: Context?,
    percentageHandler: (Int) -> Unit
): MultipartBody.Part? {
    val name = getImageNameAndSize(context)
    val progressRequestBody = context?.contentResolver?.openInputStream(this)
        ?.use {
            val byte = it.readBytes()
            println("ImageUploadLog byte.size: ${byte.size}")
            val body = byte.toRequestBody(
                contentType = "multipart/form-data".toMediaTypeOrNull()
            )
            ProgressRequestBody(
                requestBody = body,
                progressHandler = percentageHandler
            )
        }

    return MultipartBody.Part
        .createFormData("files", name?.first, progressRequestBody ?: return null)
}

class ProgressRequestBody(
    private val requestBody: RequestBody,
    private val progressHandler: (Int) -> Unit
) : RequestBody() {

    companion object {
        private const val progressUpdatesToSkip = 2
    }

    private var writeCount = 0

    override fun contentType(): MediaType? = requestBody.contentType()
    override fun contentLength(): Long = requestBody.contentLength()

    override fun writeTo(sink: BufferedSink) {
        println("ImageUploadLog writeCount: $writeCount, progressUpdatesToSkip: $progressUpdatesToSkip")
        if (writeCount >= progressUpdatesToSkip) {
            val countingSink = CountingSink(sink).buffer()
            requestBody.writeTo(countingSink)
            countingSink.flush()
        } else {
            requestBody.writeTo(sink)
        }
        writeCount++
    }

    private inner class CountingSink(delegate: Sink) : ForwardingSink(delegate) {
        private val handler = Handler(Looper.getMainLooper())
        private val total = contentLength()
        private var uploaded = 0L

        init {
            println("ImageUploadLog CountingSink init")
        }

        override fun write(source: Buffer, byteCount: Long) {
            println("ImageUploadLog write")
            super.write(source, byteCount)
            println("ImageUploadLog previous  uploaded: $uploaded")
            uploaded += byteCount
            println("ImageUploadLog new uploaded: $uploaded, byteCount: $byteCount")
            handler.post {
                val percentage = (100 * (uploaded.toFloat() / total.toFloat())).toInt()
                println("ImageUploadLog percentage: $percentage")
                progressHandler(percentage)
            }
        }
    }

Photo upload logs:

1) First Image Upload (74 KB) #Success

ImageUploadLog byte.size: 7417
ImageUploadLog writeCount: 0, progressUpdatesToSkip: 2
ImageUploadLog writeCount: 1, progressUpdatesToSkip: 2
ImageUploadLog writeCount: 2, progressUpdatesToSkip: 2
ImageUploadLog CountingSink init
ImageUploadLog write
ImageUploadLog previous  uploaded: 0
ImageUploadLog new uploaded: 7417, byteCount: 7417
ImageUploadLog percentage: 100

2) Second Image Upload (4.7 MB) #Fail

ImageUploadLog byte.size: 4788195
ImageUploadLog writeCount: 0, progressUpdatesToSkip: 2
ImageUploadLog writeCount: 1, progressUpdatesToSkip: 2
ImageUploadLog writeCount: 2, progressUpdatesToSkip: 2
ImageUploadLog CountingSink init
ImageUploadLog write
Ümit Bülbül
  • 512
  • 2
  • 15

0 Answers0