2018-01-04 19:52:25 +01:00
|
|
|
package jp.juggler.subwaytooter.util
|
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
import jp.juggler.util.log.LogCategory
|
2020-12-08 21:24:42 +01:00
|
|
|
import kotlinx.coroutines.runBlocking
|
2018-01-04 19:52:25 +01:00
|
|
|
import okhttp3.Interceptor
|
|
|
|
import okhttp3.Response
|
|
|
|
import okhttp3.ResponseBody
|
2022-06-04 20:43:55 +02:00
|
|
|
import okio.*
|
|
|
|
import java.io.IOException
|
2019-08-24 05:35:22 +02:00
|
|
|
import kotlin.math.max
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2019-08-24 05:35:22 +02:00
|
|
|
class ProgressResponseBody private constructor(
|
2021-06-20 15:12:25 +02:00
|
|
|
private val originalBody: ResponseBody,
|
2019-08-24 05:35:22 +02:00
|
|
|
) : ResponseBody() {
|
2020-12-08 21:24:42 +01:00
|
|
|
|
|
|
|
companion object {
|
|
|
|
internal val log = LogCategory("ProgressResponseBody")
|
|
|
|
|
2024-03-17 11:05:30 +01:00
|
|
|
// ProgressResponseBody を間に挟むインタセプタを作成する
|
|
|
|
fun makeInterceptor() = Interceptor { chain ->
|
2021-11-20 13:16:56 +01:00
|
|
|
val originalResponse = chain.proceed(chain.request())
|
|
|
|
originalResponse.newBuilder()
|
2023-06-29 17:24:17 +02:00
|
|
|
.body(ProgressResponseBody(originalResponse.body))
|
2021-11-20 13:16:56 +01:00
|
|
|
.build()
|
2020-12-08 21:24:42 +01:00
|
|
|
}
|
|
|
|
|
2024-03-17 11:05:30 +01:00
|
|
|
// 進捗コールバックつきでバイト列を読む
|
2020-12-08 21:24:42 +01:00
|
|
|
@Throws(IOException::class)
|
2022-06-04 20:43:55 +02:00
|
|
|
fun bytes(
|
|
|
|
response: Response,
|
|
|
|
callback: suspend (bytesRead: Long, bytesTotal: Long) -> Unit,
|
2024-03-17 11:05:30 +01:00
|
|
|
) = bytes(response.body, callback)
|
2020-12-08 21:24:42 +01:00
|
|
|
|
2024-03-17 11:05:30 +01:00
|
|
|
// 進捗コールバックつきでバイト列を読む
|
2020-12-08 21:24:42 +01:00
|
|
|
@Suppress("MemberVisibilityCanPrivate")
|
|
|
|
@Throws(IOException::class)
|
|
|
|
private fun bytes(
|
2021-06-20 15:12:25 +02:00
|
|
|
body: ResponseBody,
|
|
|
|
callback: suspend (bytesRead: Long, bytesTotal: Long) -> Unit,
|
|
|
|
): ByteArray {
|
2023-06-29 17:24:17 +02:00
|
|
|
(body as? ProgressResponseBody)?.callback = callback
|
2020-12-08 21:24:42 +01:00
|
|
|
return body.bytes()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private var callback: suspend (bytesRead: Long, bytesTotal: Long) -> Unit = { _, _ -> }
|
|
|
|
|
2024-03-17 11:05:30 +01:00
|
|
|
private val wrappedSource by lazy {
|
|
|
|
object : ForwardingSource(originalBody.source()) {
|
|
|
|
var totalBytesRead = 0L
|
|
|
|
override fun read(sink: Buffer, byteCount: Long): Long {
|
|
|
|
val bytesRead = super.read(sink, byteCount)
|
|
|
|
// read() returns the number of bytes read, or -1 if this source is exhausted.
|
|
|
|
totalBytesRead += max(0, bytesRead)
|
|
|
|
runBlocking {
|
|
|
|
callback.invoke(
|
|
|
|
totalBytesRead,
|
|
|
|
originalBody.contentLength(),
|
|
|
|
)
|
2020-12-08 21:24:42 +01:00
|
|
|
}
|
2024-03-17 11:05:30 +01:00
|
|
|
return bytesRead
|
2020-12-08 21:24:42 +01:00
|
|
|
}
|
2024-03-17 11:05:30 +01:00
|
|
|
}.buffer()
|
2020-12-08 21:24:42 +01:00
|
|
|
}
|
|
|
|
|
2024-03-17 11:05:30 +01:00
|
|
|
override fun contentType() = originalBody.contentType()
|
|
|
|
override fun contentLength() = originalBody.contentLength()
|
|
|
|
override fun source() = wrappedSource
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|