-1

I' trying to upload an image to server using retrofit2. I think that the way I send data is not correct but I haven't figure out yet where is my problem.

I should send the data in this format: {"file": image, "userID": userId}

This is my code in retrofit interace: @POST("avatar") fun uploadImage(@Body data: Data ) : Call<ResponseBody>

I have created an object Data with file and userID I don't know if this is the right way. I have seen also this example

ublic interface UploadAPIs {
@Multipart
@POST("/upload")
Call<ResponseBody> uploadImage(@Part MultipartBody.Part file, @Part("name") RequestBody requestBody);

}

But I really don't understand well, how can I sen an object with part multipart

This is how I create image file that I get from gallery in my fragment

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    if (resultCode == Activity.RESULT_OK)

        when(requestCode){
            GALLERY -> {
                val selectedImage= data!!.data

                val file = File(selectedImage.path)

                val data = Data(file, userID)

                val call = api!!.uploadImage(data)

                call.enqueue(object: Callback<ResponseBody>{
                    override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
                        Toast.makeText(context, t.message, Toast.LENGTH_SHORT).show()
                    }

                    override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
                        val response = response.body()!!.string()
                        println("Response " + response)

                        //response says user does not exist because the way I send data is not correct
                    }

                })

            }

            CAMERA -> {
             //code here
            }
        }

}

This is the class that I create for Data object

class Data (val file: File, userID: Int)

I would be grateful if anyone can help me :)

Updated code:

@Multipart
@POST("avatar")
fun uploadImage(
        @Part("userID") user_ID: RequestBody,
        @Part image: MultipartBody.Part) : Call<ResponseBody>


override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    if (resultCode == Activity.RESULT_OK)

        when(requestCode){
            GALLERY -> {
                val selectedImage= data!!.data

                val bitmap = MediaStore.Images.Media.getBitmap(context!!.contentResolver, selectedImage)
                avatar.setImageBitmap(bitmap)

                val file = File(getRealPathFromURI(selectedImage))


                val id = RequestBody.create(MediaType.parse("text/plain"), userID.toString())

                //val reqBody = RequestBody.create(MediaType.parse(activity!!.contentResolver.getType(selectedImage)!!), file)

                val reqBody = RequestBody.create(MediaType.parse("image/*"), file)

                val body = MultipartBody.Part.createFormData("file", file.name, reqBody)

                val call = api!!.uploadImage(id, body)

                call.enqueue(object: Callback<ResponseBody>{
                    override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
                        Toast.makeText(context, t.message, Toast.LENGTH_SHORT).show()
                        println("Failure")
                    }

                    override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
                        if (response.isSuccessful){
                            println("Successful " + response.body()?.string())

                        }else{
                            response.errorBody()?.string()
                            println("Error " + response.headers().toString())

                        }


                    }

                })

            }

            CAMERA -> {
               //code
            }
        }

}
Jona
  • 263
  • 1
  • 5
  • 18
  • https://stackoverflow.com/questions/39953457/how-to-upload-image-file-in-retrofit-2 – ADM Mar 01 '19 at 09:13
  • Possible duplicate of [How to upload image with Retrofit Android?](https://stackoverflow.com/questions/42338130/how-to-upload-image-with-retrofit-android) – Elio Lako Mar 01 '19 at 09:19
  • 2
    `{"file": image, "userID": userId}` looks like JSON. If it is, then you can't send image as JSON. You have to convert it to JSON-supported format (BASE64-encodede byte array for example). So first you need to make sure you understand what format the beckend expects it it in – Vladyslav Matviienko Mar 01 '19 at 09:23
  • @Vladyslav Matviienko I updated my code and now userID goes to server but file it goes undefined I am uploading my code above in my question – Jona Mar 01 '19 at 15:58
  • as I said already, nobody knows, how the server is expecting you to send it the image. – Vladyslav Matviienko Mar 01 '19 at 16:45
  • It wa a problem with server the code is ok, thank you for your response @VladyslavMatviienko – Jona Mar 04 '19 at 15:47

1 Answers1

0
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    if (resultCode == Activity.RESULT_OK)

        when(requestCode){
            GALLERY -> {
                val selectedImage= data!!.data

                val bitmap = MediaStore.Images.Media.getBitmap(context!!.contentResolver, selectedImage)
                avatar.setImageBitmap(bitmap)

                val file = File(getRealPathFromURI(selectedImage))

                val id = RequestBody.create(MediaType.parse("text/plain"), userID.toString())

                val reqBody = RequestBody.create(MediaType.parse("image/jpeg"), file)

                val body = MultipartBody.Part.createFormData("file", file.name, reqBody)

                val api = RetrofitClient.getInstance().apiService
                val call = api!!.uploadImage(id, body)

                call.enqueue(object: Callback<ResponseBody>{
                    override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
                        Toast.makeText(context, t.message, Toast.LENGTH_SHORT).show()
                        println("Failure")
                    }

                    override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
                        if (response.isSuccessful){
                            println("Successful " + response.body()?.string())

                        }else{
                            response.errorBody()?.string()
                            println("Error " + response.headers().toString())

                        }


                    }

                })


            }

            CAMERA -> {
                //code here
            }
        }

}

And in API interface:

@Multipart
@POST("avatar")
fun uploadImage(
        @Part("userID") user_ID: RequestBody,
        /*@Part("file") name: RequestBody*/
        @Part image: MultipartBody.Part) : Call<ResponseBody>
Jona
  • 263
  • 1
  • 5
  • 18