Retrofit2 无法使用 Multipart 或 RequestBody 上传图像
Retrofit2 failed to upload image with Multipart or RequestBody
我已经尝试了几种方法来为服务器发送图像,就像在 Postman 中一样
但 none 确实成功了。
第一种方式通过@Multipart:
interface Api {
@Multipart
@POST("/upload-file")
fun uploadFile(@Part("file") file: RequestBody,
@Part("data") id: FileUploadModel): Single<Response<AdvertisementResponse>>
}
存储库中的方法 class:
override fun uploadFile(
id: FileUploadModel,
filePath: String
): Single<Response<AdvertisementResponse>> {
val requestFile = RequestBody.create(MediaType.parse("image/*"), file)
return api.uploadFile(requestFile, id)
}
第二种使用RequestBody的方式:
@POST("/upload-file")
fun uploadFile(@Body requestBody: RequestBody): Single<Response<AdvertisementResponse>>
存储库中的方法 class:
override fun uploadFile(
id: FileUploadModel,
filePath: String
): Single<Response<AdvertisementResponse>> {
val file = File(filePath)
val builder = MultipartBody.Builder()
builder.setType(MultipartBody.FORM)
val requestFile = RequestBody.create(MediaType.parse("image/*"), file)
builder.addFormDataPart("file", file.name, requestFile)
builder.addFormDataPart("data", id.toJson())
return api.uploadFile(builder.build())
}
通过MultipartBody.Part的第三种方式:
@Multipart
@POST("/upload-file")
fun uploadFile(@Part("file") file: MultipartBody.Part,
@Part("data") id: FileUploadModel): Single<Response<AdvertisementResponse>>
存储库中的方法 class:
override fun uploadFile(
id: FileUploadModel,
filePath: String
): Single<Response<AdvertisementResponse>> {
val file = File(filePath)
val requestFile = RequestBody.create(MediaType.parse("image/*"), file)
val multipartFile = MultipartBody.Part.createFormData("file", file.name, requestFile)
return api.uploadFile(multipartFile, id)
}
日志显示 POST 上传文件请求未完成:
2020-08-15 13:52:35.828 D/OkHttpInterceptor: --> POST http://####/advertisement
2020-08-15 13:52:35.829 D/OkHttpInterceptor: Content-Type: application/json
2020-08-15 13:52:35.829 D/OkHttpInterceptor: Content-Length: 233
2020-08-15 13:52:35.829 D/OkHttpInterceptor: {"businessName":"mgskhsgmhz","email":"test@email.com","emirates":"Abu Dhabi","image":"/storage/emulated/0/Pictures/1768cbfe-e5eb-4ae0-b642-be2733cfedbe969168674235591475.jpg","note":"","ownerName":"mhzm","phone":"1111","website":""}
2020-08-15 13:52:35.829 D/OkHttpInterceptor: --> END POST (233-byte body)
2020-08-15 13:52:36.233 D/OkHttpInterceptor: <-- 201 Created http://####/advertisement (403ms)
2020-08-15 13:52:36.233 D/OkHttpInterceptor: X-Powered-By: Express
2020-08-15 13:52:36.234 D/OkHttpInterceptor: Access-Control-Allow-Origin: *
2020-08-15 13:52:36.234 D/OkHttpInterceptor: Content-Type: application/json; charset=utf-8
2020-08-15 13:52:36.234 D/OkHttpInterceptor: Content-Length: 303
2020-08-15 13:52:36.235 D/OkHttpInterceptor: ETag: W/"12f-hAPhr6BG9nzrhDMQ2eMpt2ypCAk"
2020-08-15 13:52:36.235 D/OkHttpInterceptor: Date: Sat, 15 Aug 2020 10:52:37 GMT
2020-08-15 13:52:36.235 D/OkHttpInterceptor: Connection: keep-alive
2020-08-15 13:52:36.237 D/OkHttpInterceptor: {"Error":{},"Data":{"_id":"5f37be7552e7000012180324","businessName":"mgskhsgmhz","email":"test@email.com","emirates":"Abu Dhabi","image":"/storage/emulated/0/Pictures/1768cbfe-e5eb-4ae0-b642-be2733cfedbe969168674235591475.jpg","note":"","ownerName":"mhzm","phone":"1111","website":""},"HasError":false}
2020-08-15 13:52:36.237 D/OkHttpInterceptor: <-- END HTTP (303-byte body)
2020-08-15 13:52:36.244 D/123: sent: 5f37be7552e7000012180324
2020-08-15 13:52:36.278 D/OkHttpInterceptor: --> POST http://####/upload-file
2020-08-15 13:52:36.278 D/OkHttpInterceptor: Content-Type: multipart/form-data; boundary=894cbe1b-0fc4-47c6-849d-3764193c214f
2020-08-15 13:52:36.279 D/OkHttpInterceptor: Content-Length: 104305
不知为何Retrofit无法完成此类请求
感谢任何建议
干杯
问题是由于无法从磁盘读取文件造成的。
使用 Android sdk 29 将 android:requestLegacyExternalStorage="true"
添加到 Android 清单对我有用。
<application
android:name=".MyApplication"
android:requestLegacyExternalStorage="true" ...
除了添加 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
权限。
我已经尝试了几种方法来为服务器发送图像,就像在 Postman 中一样
但 none 确实成功了。
第一种方式通过@Multipart:
interface Api {
@Multipart
@POST("/upload-file")
fun uploadFile(@Part("file") file: RequestBody,
@Part("data") id: FileUploadModel): Single<Response<AdvertisementResponse>>
}
存储库中的方法 class:
override fun uploadFile(
id: FileUploadModel,
filePath: String
): Single<Response<AdvertisementResponse>> {
val requestFile = RequestBody.create(MediaType.parse("image/*"), file)
return api.uploadFile(requestFile, id)
}
第二种使用RequestBody的方式:
@POST("/upload-file")
fun uploadFile(@Body requestBody: RequestBody): Single<Response<AdvertisementResponse>>
存储库中的方法 class:
override fun uploadFile(
id: FileUploadModel,
filePath: String
): Single<Response<AdvertisementResponse>> {
val file = File(filePath)
val builder = MultipartBody.Builder()
builder.setType(MultipartBody.FORM)
val requestFile = RequestBody.create(MediaType.parse("image/*"), file)
builder.addFormDataPart("file", file.name, requestFile)
builder.addFormDataPart("data", id.toJson())
return api.uploadFile(builder.build())
}
通过MultipartBody.Part的第三种方式:
@Multipart
@POST("/upload-file")
fun uploadFile(@Part("file") file: MultipartBody.Part,
@Part("data") id: FileUploadModel): Single<Response<AdvertisementResponse>>
存储库中的方法 class:
override fun uploadFile(
id: FileUploadModel,
filePath: String
): Single<Response<AdvertisementResponse>> {
val file = File(filePath)
val requestFile = RequestBody.create(MediaType.parse("image/*"), file)
val multipartFile = MultipartBody.Part.createFormData("file", file.name, requestFile)
return api.uploadFile(multipartFile, id)
}
日志显示 POST 上传文件请求未完成:
2020-08-15 13:52:35.828 D/OkHttpInterceptor: --> POST http://####/advertisement 2020-08-15 13:52:35.829 D/OkHttpInterceptor: Content-Type: application/json 2020-08-15 13:52:35.829 D/OkHttpInterceptor: Content-Length: 233 2020-08-15 13:52:35.829 D/OkHttpInterceptor: {"businessName":"mgskhsgmhz","email":"test@email.com","emirates":"Abu Dhabi","image":"/storage/emulated/0/Pictures/1768cbfe-e5eb-4ae0-b642-be2733cfedbe969168674235591475.jpg","note":"","ownerName":"mhzm","phone":"1111","website":""} 2020-08-15 13:52:35.829 D/OkHttpInterceptor: --> END POST (233-byte body) 2020-08-15 13:52:36.233 D/OkHttpInterceptor: <-- 201 Created http://####/advertisement (403ms) 2020-08-15 13:52:36.233 D/OkHttpInterceptor: X-Powered-By: Express 2020-08-15 13:52:36.234 D/OkHttpInterceptor: Access-Control-Allow-Origin: * 2020-08-15 13:52:36.234 D/OkHttpInterceptor: Content-Type: application/json; charset=utf-8 2020-08-15 13:52:36.234 D/OkHttpInterceptor: Content-Length: 303 2020-08-15 13:52:36.235 D/OkHttpInterceptor: ETag: W/"12f-hAPhr6BG9nzrhDMQ2eMpt2ypCAk" 2020-08-15 13:52:36.235 D/OkHttpInterceptor: Date: Sat, 15 Aug 2020 10:52:37 GMT 2020-08-15 13:52:36.235 D/OkHttpInterceptor: Connection: keep-alive 2020-08-15 13:52:36.237 D/OkHttpInterceptor: {"Error":{},"Data":{"_id":"5f37be7552e7000012180324","businessName":"mgskhsgmhz","email":"test@email.com","emirates":"Abu Dhabi","image":"/storage/emulated/0/Pictures/1768cbfe-e5eb-4ae0-b642-be2733cfedbe969168674235591475.jpg","note":"","ownerName":"mhzm","phone":"1111","website":""},"HasError":false} 2020-08-15 13:52:36.237 D/OkHttpInterceptor: <-- END HTTP (303-byte body) 2020-08-15 13:52:36.244 D/123: sent: 5f37be7552e7000012180324 2020-08-15 13:52:36.278 D/OkHttpInterceptor: --> POST http://####/upload-file 2020-08-15 13:52:36.278 D/OkHttpInterceptor: Content-Type: multipart/form-data; boundary=894cbe1b-0fc4-47c6-849d-3764193c214f 2020-08-15 13:52:36.279 D/OkHttpInterceptor: Content-Length: 104305
不知为何Retrofit无法完成此类请求
感谢任何建议
干杯
问题是由于无法从磁盘读取文件造成的。
使用 Android sdk 29 将 android:requestLegacyExternalStorage="true"
添加到 Android 清单对我有用。
<application
android:name=".MyApplication"
android:requestLegacyExternalStorage="true" ...
除了添加 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
权限。