Alexander Black
11/17/2020, 7:02 PMsuspend fun HttpClient.downloadFile(
output: File,
downloadUrl: Url,
md5Hash: String
): Flow<DownloadResult> {
return flow {
try {
val response = get<HttpResponse> { url(downloadUrl) }
val data = ByteArray(response.contentLength()?.toInt() ?: 0)
var offset = 0
do {
val progress = (offset.toDouble() / data.size) * 100
emit(DownloadResult.Progress(progress))
val currentRead = response.content.readAvailable(data, offset, data.size)
offset += currentRead
} while (currentRead > 0)
if (response.status.isSuccess()) {
if (data.md5().hex == md5Hash) {
output.write(data)
emit(DownloadResult.Success)
} else {
emit(DownloadResult.ErrorCorruptFile)
}
} else {
emit(DownloadResult.ErrorBadResponseCode(response.status.value))
}
} catch (e: TimeoutCancellationException) {
emit(DownloadResult.ErrorRequestTimeout("Connection timed out", e))
} catch (t: Throwable) {
emit(DownloadResult.Error("Failed to connect", t))
}
}
}
The problem is that the response.content.readAvailable()
method always seems to read the whole file at once without chunking it up, which means my progress emission only gets outputted once. I’m wondering if there’s something I’m doing wrong here? or if that’s normal behaviour? Also as a side note the file I’m testing on is 25MB so it should emit a few times I’d think.tateisu
11/18/2020, 7:10 AMJulius
11/18/2020, 10:14 AMAlexander Black
11/18/2020, 2:19 PM