How to post this body type form-data using retrofit. I tried with #Part but image is not getting save on server. Any idea where I'm making a mistake?
#Multipart
#POST("/saveData")
Call<MyResponse> saveImage(
#Part("empsno") String empsno,
#Part("lrSno") String lrsno,
#Part("deliveryDate") String deliverydate,
#Part("deliveryTime") String delvrytime,
#Part("uploadFile") String upldfile,
#Part("remarks") String remark,
#Part("receivedBy") String recvdby,
#Part("place") String place,
#Part("ipAddress") String ip,
#Part MultipartBody.Part images
);
By using form data I'm successfully able to post data:
I made changes String to ResponseBody and now everything working fine
#Multipart
#POST("/saveData")
Call<MyResponse> saveImage(
#Part("empsno") ResponseBody empsno,
#Part("lrSno") ResponseBody lrsno,
#Part("deliveryDate") ResponseBody deliverydate,
#Part("deliveryTime") ResponseBody delvrytime,
#Part("uploadFile") ResponseBody upldfile,
#Part("remarks") ResponseBody remark,
#Part("receivedBy") ResponseBody recvdby,
#Part("place") ResponseBody place,
#Part("ipAddress") ResponseBody ip,
#Part MultipartBody.Part images
);
Related
I'm sending a multipart request to server and this is my interface:
#Multipart
#POST("v1/group/new")
Call<MyResponse> newGroup(
#Header("token") String token,
#Part MultipartBody.Part photo,
#Part("title") RequestBody subject,
#Part("members") List<RequestBody> members);
and for sending my members in my fragment, I change my List<String> to List<RequestBody> as below:
List<RequestBody> members = new ArrayList<>();
for(int i = 0;i < membersId.size(); i++){
members.add(RequestBody.create(MediaType.parse("text/plain"),membersId.get(i)));
}
and it's working with multiple members! but when there is a one string in my list, retrofit doesn't sends my members as a list!!! for example:
I want to send array of strings like this :
["item1","item2","item3"]
my code works for this, but when there is only one item, retrofit sends this :
"item1"
instead of ["item1"]
what is the proper way of sending array of string in multipart with retrofit?
what am I doing wrong?
Use something like this.
#Multipart
#POST("v1/group/new")
Call<MyResponse> newGroup(
#Header("token") String token,
#Part MultipartBody.Part photo,
#Part("title") RequestBody subject,
#Part("members[]") List<RequestBody> members);
Remember you must add [] to your members param :).
#Multipart
#POST("v1/group/new")
Call<MyResponse> newGroup(
#Header("token") String token,
#Part MultipartBody.Part photo,
#Part("title") RequestBody subject,
#Part("members[]") ArrayList<RequestBody> members);
Two changes:
Change list to ArrayList as ArrayList is Serializable whereas List is not.
add "[]" at the end of the ArrayList type parameter.
I have an ArrayList of custom objects, each with about 10 fields, that I already managed to upload to our server. The problem is that one of the fields is a String which contains a Base64-encoded string that I converted from a file, which the Retrofit Gson creater does not seem to like. This problem could be solved by just sending all the fields without the image, and then after that upload all the images using ftp, but it would be so much easier if I could just put the image in the object somehow.
Question: How can I send a Base64-encoded string as a field inside a custom object to a url using Retrofit?
#FormUrlEncoded
#POST("/UploadImages")
Call<ResponseBody> postImages(#Body ArrayListImage img);
//POJO CLASS
public class ArrayListImage {
#SerializedName("image")
#Expose
private ArrayList<String> image;
public ArrayListImage(ArrayList<String> image) {
this.image=image;
}
}
Below is the RequestBody code which i use to upload file using Retrofit:
RequestBody lRequestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part lFile = MultipartBody.Part.createFormData("file", file.getName(), lRequestBody);
MultipartBody.Part title = MultipartBody.Part.createFormData("title", file.getName());
MultipartBody.Part lFilenamebase64 = MultipartBody.Part.createFormData("filenamebase64", base64EncodedFileName);
To encode file name:
String base64EncodedFileName = Base64.encodeToString(file.getName().getBytes(Charsets.UTF_8), Base64.URL_SAFE | Base64.NO_WRAP);
I defined the api like:
#Multipart
#POST("/upload")
Observable<Response<ResponseBody>> uploadFile(#Part MultipartBody.Part file, #Part MultipartBody.Part title, #Part MultipartBody.Part base64EncodedFileName);
I hope it might help you.
//Convert Object list into json string.
Gson gson = new Gson();
String objListString = gson.toJson(objectList);
#FormUrlEncoded
#POST("********")
Call<JsonObject> sendObjectList(#Field("objListString") String objListString);
And at the web end parse string into json.
#enjoy
#FormUrlEncoded
#POST("/api/post")
Call<Response> createPost(
#Header("auth") String auth,
#Field("id") String id,
#Field("title") String title,
#Body ContentData content);
By using this code am getting error saying "#Body parameters cannot be used with form or multi-part encoding.". What should i do now ? I tried to send Object as String that also failed.
If you are sending form-data use Field for your parameters:
#Header("auth: YOUR_AUTH")
#FormUrlEncoded
#POST("/api/post")
Call<Response> createPost(
#Field("id") String id,
#Field("title") String title
);
else if you are using other than form-data like application/json Send your body by #Body:
#Header("auth: YOUR_AUTH")
#POST("/api/post")
Call<Response> createPost(#Body ContentData content);
This all depends upon your requirements.
Here I m using #Fields data with #FormUrlEncoded But I have to use both in same API #Part("user_image") RequestBody file with #Multipart. How does it possible? Thanks in advance.
#FormUrlEncoded
#POST("/datingapp/index.php/Webservice")
Call<Result> signupUser(#Field("user_name") String name,
#Field("age") String age,
#Field("work") String work,
#Field("home_town") String home_town,
#Field("gender") String gender,
#Field("interest") String interest,
#Field("study") String study,
#Field("email") String email,
#Field("password") String password,
#Field("device_id") String device_id,
#Field("device_type") String device_type,
#Part("user_image") RequestBody file,
#Field("signup") String signup);
Http protocol not allow 2 Content-Type in the same request. So you have to choose :
application/x-www-form-urlencoded
multipart/form-data
You use application/x-www-form-urlencoded by using annotation #FormUrlEncoded in order to send image you have to transform the whole file into text (e.g. base64).
A better approach would be use multipart/form-data by describing your request like that :
#Multipart
#POST("/datingapp/index.php/Webservice")
Call<Result> signupUser(#Part("user_name") String name,
#Part("age") String age,
#Part("work") String work,
#Part("home_town") String home_town,
#Part("gender") String gender,
#Part("interest") String interest,
#Part("study") String study,
#Part("email") String email,
#Part("password") String password,
#Part("device_id") String device_id,
#Part("device_type") String device_type,
#Part("user_image") RequestBody file,
#Part("signup") String signup);
#Multipart
#POST("/datingapp/index.php/Webservice")
Call<Result> signupUser(#PartMap Map<String,String> queryMap,
#Part("user_image") RequestBody file);
Here the #PartMap contains the required other parameters which is nothing but a HashMap containing key and values e.g,
LinkedHashMap<String,String> map = new LinkedHashMap<String,String>();
map.put("user_name",username);
like above and so on.
Make api call like this :
#POST("/datingapp/index.php/Webservice")
#FormUrlEncoded
#Multipart
Call<Result> signupUser(#FieldMap LinkedHashMap<String, String> data,#Part RequestBody file);
and pass your data is the form of key and value in LinkedHashMap like this
LinkedHashMap<String, String> data = new LinkedHashMap<>();
data.put("user_name", user_name);
data.put("age", age);
data.put("work", work);
data.put("work", work);
data.put("gender", gender); and so on ....
for getting image in Multiparts :
RequestBody file= RequestBody.create(MediaType.parse("image/jpeg"), file);
final call to hit the api :
Call<Result> call = apiService.signupUser(data ,file);
Hope this works :)
I'm trying upload a Image from my Android APP to Amazon AWS S3 and I need use AWS Restful API.
I'm using Retrofit 2 to make to the request.
My application is connecting successfully with Amazon S3 and performing the request as expected, but when I try to view the Image from the Bucket, the picture does not open. I downloaded the Image to my pc and tried to open but keep getting the message that the image is corrupted.
Lets see my complete code bellow.
My Gradle dependencies
compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta1'
compile 'net.danlew:android.joda:2.8.2'
Here is created a File and starts the request
File file = new File(mCurrentPhotoPath);
RequestBody body = RequestBody.create(MediaType.parse("image/jpeg"), file);
uploadImage(body, "photo_name.jpeg");
Retrofit Interface
public interface AwsS3 {
#Multipart
#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,
#Part("Body") RequestBody body);
}
Utils class to the mount the credentials
public class AWSOauth {
public static String getOAuthAWS(Context context, String fileName) throws Exception{
String secret = context.getResources().getString(R.string.s3_secret);
String access = context.getResources().getString(R.string.s3_access_key);
String bucket = context.getResources().getString(R.string.s3_bucket);
return gerateOAuthAWS(secret, access, bucket,fileName);
}
private static String gerateOAuthAWS(String secretKey, String accessKey, String bucket, String imageName) throws Exception {
String contentType = "image/jpeg";
DateTimeFormatter fmt = DateTimeFormat.forPattern("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z").withLocale(Locale.US);
String ZONE = "GMT";
DateTime dt = new DateTime();
DateTime dtLondon = dt.withZone(DateTimeZone.forID(ZONE)).plusHours(1);
String formattedDate = dtLondon.toString(fmt);
String resource = "/" + bucket + "/" + imageName;
String stringToSign = "PUT" + "\n\n" + contentType + "\n" + formattedDate + "\n" + resource;
Mac hmac = Mac.getInstance("HmacSHA1");
hmac.init(new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA1"));
String signature = ( Base64.encodeToString(hmac.doFinal(stringToSign.getBytes("UTF-8")), Base64.DEFAULT)).replaceAll("\n", "");
String oauthAWS = "AWS " + accessKey + ":" + signature;
return oauthAWS;
}
}
Lastly the method to make a request
public void uploadImage(RequestBody body, String fileName){
String bucket = getString(R.string.s3_bucket);
Retrofit restAdapter = new Retrofit.Builder()
.baseUrl("http://" + bucket + ".s3.amazonaws.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
AwsS3 service = restAdapter.create(AwsS3.class);
DateTimeFormatter fmt = DateTimeFormat.forPattern("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z").withLocale(Locale.US);
String ZONE = "GMT";
DateTime dt = new DateTime();
DateTime dtLondon = dt.withZone(DateTimeZone.forID(ZONE)).plusHours(1);
String formattedDate = dtLondon.toString(fmt);
try {
String oauth = AWSOauth.getOAuthAWS(getApplicationContext(), fileName);
Call<String> call = service.upload(fileName, body.contentLength(), "/**", bucket + ".s3.amazonaws.com", formattedDate, body.contentType().toString(), oauth, body);
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Response<String> response) {
Log.d("tag", "response : " + response.body());
}
#Override
public void onFailure(Throwable t) {
Log.d("tag", "response : " + t.getMessage());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
I appreciate any helps, thanks in advance!
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();
}
});
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
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 haven't used Retrofit 2, just Retrofit 1, so YMMV, but I believe that the typical way to do what you're trying to do is to use TypedFile where you are attempting to use RequestBody.
I'm guessing that Retrofit uses RequestBody internally.
You would create the TypedFile something like:
TypedFile typedFile = new TypedFile("multipart/form-data", new File("path/to/your/file"));
and your interface would be:
#Multipart
#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,
#Part("Body") TypedFile body);
}
There's a decent example at
https://futurestud.io/blog/retrofit-how-to-upload-files/
You can use retrofit 2 to upload the image/file
#Multipart
#POST("/api/attachment")
Call<JsonPrimitive> addAttachment(#Part MultipartBody.Part imageFile);
Now to make the call:
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part imageFileBody = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
Note : Make sure you are using retrofit2 as for some reason I was unable to upload image using retrofit1 library.