I want to upload a binary file to the server in Android. I test Api method by postman:
And it's OK, as you see there is another option which you can upload files as form data(key, value):
Every tutorials (like this one)describe how to upload files as multipart/form-data
:
// create RequestBody instance from file RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file); // MultipartBody.Part is used to send also the actual file name MultipartBody.Part body = MultipartBody.Part.createFormData("picture", file.getName(), requestFile);
I search a lot but couldn't find any way to upload file as binary with retrofit2.
There is just one Issue in retrofit repository which ask How can I POST a image binary in retrofit 2.0 beta?. I use its solution :
API Service:
@POST("trip/{tripId}/media/photos") Call<MediaPost> postEventPhoto( @Path("eventId") int tripId, @Header("Authorization") String accessToken, @Query("direction") String direction, @Body RequestBody photo);
Caller:
InputStream in = new FileInputStream(new File(media.getPath())); byte[] buf; buf = new byte[in.available()]; while (in.read(buf) != -1); RequestBody requestBody = RequestBody .create(MediaType.parse("application/octet-stream"), buf); Call<MediaPost> mediaPostCall = tripApiService.postTripPhoto( tripId, ((GlobalInfo) getApplicationContext()).getApiAccessToken(), direction, requestBody);
But I got this error:
java.lang.IllegalArgumentException: @Body parameters cannot be used with form or multi-part encoding.
What's wrong with my code? what should I do?
To upload a binary file, create a multipart request with a part that contains the JSON request body required by the resource, and a part for each file you want to upload. Each file must have its own part. To upload binary data to multiple fields, add a part for each field. The part names must match the field names.
Just adding another solution, as I had to dig a bit to understand what happened in the question in the first place.
My solution is to get the binary file as a byte[]
directly and then put it inside the RequestBody
. So in the end, the code would look like this:
interface RetrofitService { @POST("api/v1/upload_file") Call<Void> uploadBinaryFile(@Body RequestBody body); }
And to call it:
public void uploadBinaryFile(File fileToUpload) { retrofitService .uploadBinaryFile(RequestBody.create(MediaType.parse("application/octet"), Files.readAllBytes(fileToUpload)); }
This is basically the same as OP's original question, but just for the sake of clarity I'll leave this answer as well for the next reader.
After hours of searching I found that there was an @Multipart
annotation remains in API interface of my code from last example! which prevent to send binary data to the server and the solution in retrofit repository was OK!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With