AWS S3 Rest API with Android Retrofit V2 library, uploaded image is damaged
You are sending a multipart payload, but forcing the Content-type to be image/jpeg
. Your jpg is corrupt because S3 probably saved the multipart headers into your jpg file since you told it the whole message was a JPG. Since you do not actually have multiple parts to send, you can drop the Multipart
annotation and use Body
instead of Part
for your RequestBody
public interface AwsS3 {
@PUT("/{Key}")
Call<String> upload(@Path("Key") String Key,
@Header("Content-Length") long length,
@Header("Accept") String accept,
@Header("Host") String host,
@Header("Date") String date,
@Header("Content-type") String contentType,
@Header("Authorization") String authorization,
@Body RequestBody body);
}
You should also be able to remove explicitly setting the Content-type
and Content-length
headers.
I have the same problem, and as I use Fiddler checked the HTTP request content, I found retrofit 2.0.0 beta1 has a different with 1.9.0.
In my problem, the different of HTTP request content prevent server get the correct data.
In order to make a same HTTP request content, i do next steps using retrofit 2.0.0 deta1.
In the retrofit service, add a form-data header for the http request;
@Headers("Content-Type: multipart/form-data;boundary=95416089-b2fd-4eab-9a14-166bb9c5788b")
int retrofit 2.0.0 deta1
, the header using @Multipart
will get a data like this:
Content-Type: multipart/mixed
as the deafult value is mixed, and has no boundary title.
Do not using @Multipart
to upload file, just using @Body
RequestBody
if you using @Multipart
to request Server, you have to pass param(file) through
@Part(key)
, then a new problem you will get. May be retrofit 2.0.0beta1 has a BUG ..., @Multipart
generate a bad http request compile with 1.9.0.
When you call the method, you need pass MultipartRequestBody to @Body RequestBody
Using MultipartBuilder
to create a MultipartRequestBody
, when you new MultipartBuilder
, call this consturt:
new MultipartBuilder("95416089-b2fd-4eab-9a14-166bb9c5788b")
the param is you set int @headers(boundary=)
builder.addFormDataPart(String name, String filename, RequestBody value)
This method will help form a data like below int HTTP request content:
Content-Disposition: form-data; name="imgFile"; filename="IMG_20150911_113029.jpg" Content-Type: image/jpg Content-Length: 1179469
RequestBody
value is what you has generate in your code.
I just resolve this problem temporary.
Hope can help you!
RequestBody avatarBody = RequestBody.create(MediaType.parse("image"),file);
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(), avatarBody);
@Multipart
@POST(url)
Call<ResponseBody> uploadImageAmazon(
@Part MultipartBody.Part filePart);
I had same experience, and solved it by https://github.com/square/retrofit/issues/2424 this solution
I have used Retrofit 2 resolve
and I use Body
instead of Part
for your RequestBody
in interface
@PUT("")
Call<String> nameAPI(@Url String url, @Body RequestBody body);
and java code
// Prepare image file
File file = new File(pathImg);
RequestBody requestBody = RequestBody.create(MediaType.parse("image/jpeg"), file);
Call<String> call = SingletonApiServiceS3.getInstance().getService().nameAPI(
path,
requestBody
);
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, final Response<String> response) {
if (response.isSuccessful()) {
// Your handling
} else {
// Your handling
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Toast.makeText(getContext(), "onFailure : "+t.getMessage().toString(),Toast.LENGTH_SHORT).show();
}
});