Reputation: 1
I am receiving a big file from the server which I cannot hold in memory, hence receiving it in chunked encoded response and reading it through the okhttp Response.body().source()
into a buffer and writing it to a file as below.
val downloadFileBuffer = ByteArray(1024)
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.d("DOCUMENT_CONVERSION", "FAILED", e)
}
override fun onResponse(call: Call, response: Response) {
if (response.isSuccessful) {
val source = response.body()?.source()
while (!source?.exhausted()!!) {
source?.read(downloadFileBuffer)
downloadFileStream.write(downloadFileBuffer) // downloadFileStream being a FileOutputStream
}
response.close()
} else {
// error handling
response.close()
}
}
})
chunked responses will end with an empty zero byte chunk being received. In order to write the whole file on disk I need to check whether the whole response till the end zero byte chunk has been received or not.
I want to know whether okhttp have an internal mechanism to check whether the chunked response is complete or not through onFailure
or any other way or it should be handle at application level by me ? What if there is a network failure during the transfer and last few bytes would not have been recieved making the files corrupt ?
Upvotes: 0
Views: 585
Reputation: 13488
onFailure won't be called if you get a chunked response and then it fails during the response transfer.
You will receive an IOException from a call to source.read if the transfer does not complete.
A cleaner example of this loop is here https://github.com/square/okhttp/blob/c194980c7f0feee59c978766c1acf5c66167994c/okcurl/src/main/kotlin/okhttp3/curl/Main.kt#L139-L143
val source = response.body!!.source()
while (!source.exhausted()) {
out.write(source.buffer, source.buffer.size)
out.flush()
}
Upvotes: 1