If your current code uploads chunks in parallel, switch to sequential upload and ensure each chunk uses its own byte array.
Example full upload loop:
private suspend fun uploadFileInChunks(
context: Context,
uri: Uri,
uploadId: String,
isFile: Boolean
): Boolean {
try {
val mimeType =
context.contentResolver.getType(uri)
?: "application/octet-stream"
val fileName = getFileName(context, uri)
val chunkFiles = splitFileIntoChunks(
context,
uri,
uploadId
)
val totalChunks = chunkFiles.size
Log.d(
"ChunkUpload",
"Uploading $totalChunks chunks for $fileName"
)
for ((index, chunkFile) in chunkFiles.withIndex()) {
val blob = chunkFile.readBytes()
Log.d(
"ChunkUpload",
"UploadId=$uploadId Chunk=$index Size=${blob.size}"
)
if (index == 0) {
val header = blob
.take(32)
.joinToString("") {
"%02x".format(it)
}
Log.d(
"ChunkUpload",
"FIRST CHUNK HEADER=$header"
)
}
val requestBody =
blob.toRequestBody(
"application/octet-stream".toMediaType()
)
val chunkBody =
MultipartBody.Part.createFormData(
"chunk",
chunkFile.name,
requestBody
)
val response = if (isFile) {
ApiClient.apiFiles.uploadChunkForFiles(
uploadId = uploadId.toRequestBody("text/plain".toMediaType()),
chunkIndex = index.toString()
.toRequestBody("text/plain".toMediaType()),
totalChunks = totalChunks.toString()
.toRequestBody("text/plain".toMediaType()),
originalName = fileName
.toRequestBody("text/plain".toMediaType()),
mimeType = mimeType
.toRequestBody("text/plain".toMediaType()),
chunk = chunkBody
)
} else {
ApiClient.apiFiles.uploadChunk(
uploadId = uploadId.toRequestBody("text/plain".toMediaType()),
chunkIndex = index.toString()
.toRequestBody("text/plain".toMediaType()),
totalChunks = totalChunks.toString()
.toRequestBody("text/plain".toMediaType()),
originalName = fileName
.toRequestBody("text/plain".toMediaType()),
mimeType = mimeType
.toRequestBody("text/plain".toMediaType()),
chunk = chunkBody
)
}
if (!response.isSuccessful ||
response.body()?.ok != true
) {
Log.e(
"ChunkUpload",
"Chunk upload failed index=$index"
)
return false
}
Log.d(
"ChunkUpload",
"Chunk uploaded ${index + 1}/$totalChunks"
)
}
// Cleanup chunk files
chunkFiles.forEach {
try {
it.delete()
} catch (_: Exception) {
}
}
Log.d(
"ChunkUpload",
"All chunks uploaded successfully"
)
return true
} catch (e: Exception) {
Log.e(
"ChunkUpload",
"uploadFileInChunks failed",
e
)
return false
}
}
Update your splitFileIntoChunks() as well:
private fun splitFileIntoChunks(
context: Context,
uri: Uri,
uploadId: String
): List<File> {
val chunkFiles = mutableListOf<File>()
context.contentResolver.openInputStream(uri)?.use { stream ->
val buffer = ByteArray(CHUNK_SIZE)
var bytesRead: Int
var chunkIndex = 0
while (stream.read(buffer).also { bytesRead = it } > 0) {
val chunkBytes = buffer.copyOf(bytesRead)
val chunkFile = File(
context.cacheDir,
"${uploadId}_${String.format("%06d", chunkIndex)}.part"
)
FileOutputStream(chunkFile).use {
it.write(chunkBytes)
}
chunkFiles.add(chunkFile)
chunkIndex++
}
}
return chunkFiles
}
Sign up here with your email
ConversionConversion EmoticonEmoticon