Daniil Andreev
Daniil Andreev

Reputation: 41

How to send a file multipart body with retrofit2?

I have a kotlin app. I need to send a file to the server with retrofit2. I have an Intent that I get in onActivityResult. Here is my retrofit

@Multipart
@POST("audio/upload")
fun uploadAudio(
    @Part("file") file: MultipartBody.Part,
    @Field("title") title: String,
    @Field("description") description: String,
    @Field("writer") writer: String,
    @Field("privacy") privacy: Int,
    @Field("duration") duration: Int,
    @Field("secretLink") secretLink: String,
    @Field("isForKids") isForKids: Boolean,
    @Field("language") language: String,
    @Field("tags") tags: List<String>,
): Call<Any>

Here is how I use this code:

val file = File(newAudio?.path!!)

val requestFile: RequestBody = RequestBody.create(MediaType.parse("multipart/form-data"), newAudio?.path!!)

val multipartBody = MultipartBody.Part.createFormData("file", file.name, requestFile)

RetrofitService().uploadAudio(
    multipartBody,
    title!!,
    description!!,
    sharedPreferences?.getString("token", null).toString(),
    privacy!!,
    audioDuration!! / 1000,
    secretLink.text.toString(),
    forKids!!,
    language!!,
    tagAdapter.tags
).enqueue(object : Callback<Any> {
    @SuppressLint("LogNotTimber")
    override fun onFailure(call: Call<Any>, t: Throwable) {
        d("#Error", "${t.message}")
        mainContent.visibility = VISIBLE
        newAudioProgressBar.visibility = GONE

        Toast.makeText(requireContext(), t.message, Toast.LENGTH_SHORT).show()
    }

    @SuppressLint("LogNotTimber")
    override fun onResponse(call: Call<Any>, response: Response<Any>) {
        navHostFragment.findNavController().navigate(R.id.myAudiosFragment)
        Toast.makeText(requireContext(), "Audio uploaded successfully!", Toast.LENGTH_SHORT).show()
    }
})

newAudio equals data.getData(). My error is: @Part parameters using the MultipartBody.Part must not include a part name in the annotation. I tried to use PartMap as in other answers but it gives me an error: Type mismatch: inferred type is MultipartBody.Part! but Map<String, RequestBody> was expected. Help me please.

Upvotes: 1

Views: 1745

Answers (1)

Eko S. Purnomo
Eko S. Purnomo

Reputation: 61

Meybe you can use with this approach

@POST("audio/upload")
     fun uploadAudio(
        @Body partFile: RequestBody
    ): Observable<Response<PhotoProfileResponse>>

And here the requestBody which you pass to Retrofit Intercace

val file = File(newAudio?.path!!)
val builder = MultipartBody.Builder()
builder.setType(MultipartBody.FORM)
builder.addFormDataPart("title", title!!)
builder.addFormDataPart("description", description!!)
builder.addFormDataPart(
                "file", file.name, file
                    .asRequestBody("multipart/form-data".toMediaTypeOrNull())
            )
    
val requestBody = builder.build()

Upvotes: 3

Related Questions