https://stackoverflow.com/questions/70091340/how-to-upload-large-file-to-the-server-using-retrofit-multipart

    1. class UploadHelper {
    2. private val params = mutableMapOf<String, RequestBody>()
    3. interface OnResultListener {
    4. fun result(body: ResponseBody?)
    5. }
    6. inner class Builder(val params: Map<String, RequestBody>) {
    7. fun sendRequest(
    8. url: String,
    9. listener: ProgressListener? = null,
    10. resultListener: OnResultListener? = null
    11. ) {
    12. // ProgressManager.getInstance()
    13. // .addResponseListener(
    14. // StringBuilder().append(NetWorkManager.instance.getBaseUrl())
    15. // .append(url).toString(), listener
    16. // )
    17. try {
    18. HandleFileManager.instance.create(CommonService::class.java)
    19. .uploadFileMap(url, params).enqueue(object : retrofit2.Callback<ResponseBody> {
    20. override fun onResponse(
    21. call: Call<ResponseBody>,
    22. response: Response<ResponseBody>
    23. ) {
    24. resultListener?.result(response.body())
    25. }
    26. override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
    27. resultListener?.result(null)
    28. }
    29. })
    30. } catch (e: Exception) {
    31. resultListener?.result(null)
    32. // ProgressManager.getInstance().notifyOnErorr(url, e)
    33. }
    34. }
    35. }
    36. /**
    37. * 加入參数
    38. * 依据传进来的Object对象来推断是String还是File类型的參数
    39. */
    40. fun addParameter(key: String, o: Any): UploadHelper {
    41. if (o is String) {
    42. val body = o.toRequestBody("text/plain;charset=UTF-8".toMediaType())
    43. params[key] = body
    44. } else if (o is File) {
    45. //注意不要使用byteArray 如果上传文件>90M 会报OOM内存溢出
    46. //https://stackoverflow.com/questions/70091340/how-to-upload-large-file-to-the-server-using-retrofit-multipart
    47. val body =
    48. o.asRequestBody("multipart/form-data;charset=UTF-8".toMediaType())
    49. // params["file\"; filename=\"" + o.name] = body
    50. //注意上传多个文件一定要用 key 如果用"file\"只能上传一个文件
    51. //HTTP的格式:
    52. //name=key;filename=0.name xxxxxx
    53. //name=key;filename=0.name xxxxxx
    54. //......
    55. params[key + "\"; filename=\"" + o.name + ""] = body
    56. }
    57. return this
    58. }
    59. //File.byteArray ktx 可直接转换
    60. // fun changeByteArray(file: File): ByteArray {
    61. // val fis = FileInputStream(file)
    62. // file.readBytes()
    63. // val swapStream = ByteArrayOutputStream()
    64. // //将数据优先 存储到缓存区,最后在同步到stream 不要直接操作文件
    65. // val buff = ByteArray(1024 * 4) //buff用于存放循环读取的临时数据
    66. // var rc = 0
    67. // while (fis.read(buff, 0, 100).also { rc = it } > 0) {
    68. // swapStream.write(buff, 0, rc)
    69. // }
    70. // return swapStream.toByteArray()
    71. // }
    72. /**
    73. * 构建RequestBody
    74. */
    75. fun bulider(): Builder {
    76. return Builder(params)
    77. }
    78. public fun clear() {
    79. params.clear();
    80. }
    81. }

    多文件上传

    1. @Multipart
    2. @POST
    3. fun uploadFileMap(
    4. @Url url: String,
    5. @PartMap body: Map<String, @JvmSuppressWildcards RequestBody>
    6. ): Call<ResponseBody>