NetRequestBody.kt 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * Copyright (C) 2018 Drake, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.drake.net.body
  17. import android.os.SystemClock
  18. import com.drake.net.component.Progress
  19. import com.drake.net.interfaces.ProgressListener
  20. import okhttp3.MediaType
  21. import okhttp3.RequestBody
  22. import okio.*
  23. import java.io.IOException
  24. import java.util.concurrent.ConcurrentLinkedQueue
  25. class NetRequestBody(
  26. private val requestBody: RequestBody,
  27. private val progressListeners: ConcurrentLinkedQueue<ProgressListener>? = null
  28. ) : RequestBody() {
  29. private val progress = Progress()
  30. val contentLength by lazy { requestBody.contentLength() }
  31. override fun contentType(): MediaType? {
  32. return requestBody.contentType()
  33. }
  34. @Throws(IOException::class)
  35. override fun contentLength(): Long {
  36. return contentLength
  37. }
  38. @Throws(IOException::class)
  39. override fun writeTo(sink: BufferedSink) {
  40. if (sink is Buffer ||
  41. sink.toString().contains("com.android.tools.profiler.support.network.HttpTracker\$OutputStreamTracker")) {
  42. requestBody.writeTo(sink)
  43. } else {
  44. val bufferedSink: BufferedSink = sink.toProgress().buffer()
  45. requestBody.writeTo(bufferedSink)
  46. bufferedSink.close()
  47. }
  48. }
  49. /**
  50. * 复制一段指定长度的字符串内容
  51. * @param byteCount 复制的字节长度. 如果-1则返回完整的字符串内容
  52. * @param discard 如果实际长度大于指定长度则直接返回null. 可以保证数据完整性
  53. */
  54. fun peekString(byteCount: Long = 1024 * 1024, discard: Boolean = false): String {
  55. val buffer = Buffer()
  56. requestBody.writeTo(buffer)
  57. if (discard && buffer.size > byteCount) return ""
  58. val byteCountFinal = if (byteCount < 0) buffer.size else minOf(buffer.size, byteCount)
  59. return buffer.readUtf8(byteCountFinal)
  60. }
  61. private fun Sink.toProgress() = object : ForwardingSink(this) {
  62. var writeByteCount = 0L
  63. @Throws(IOException::class)
  64. override fun write(source: Buffer, byteCount: Long) {
  65. super.write(source, byteCount)
  66. writeByteCount += byteCount
  67. if (progressListeners != null) {
  68. val currentElapsedTime = SystemClock.elapsedRealtime()
  69. progressListeners.forEach { progressListener ->
  70. progressListener.intervalByteCount += byteCount
  71. val currentInterval = currentElapsedTime - progressListener.elapsedTime
  72. if (currentInterval >= progressListener.interval || writeByteCount == contentLength) {
  73. progressListener.onProgress(
  74. progress.apply {
  75. currentByteCount = writeByteCount
  76. totalByteCount = contentLength
  77. intervalByteCount = progressListener.intervalByteCount
  78. intervalTime = currentInterval
  79. }
  80. )
  81. progressListener.elapsedTime = currentElapsedTime
  82. progressListener.intervalByteCount = 0L
  83. }
  84. }
  85. }
  86. }
  87. }
  88. }