What is the best way to send a file using the RestService? I have an image that I have to send to the server.
The API expects the following POST data:
image -> image I want to send
description -> text
title -> text
Can I just send an object with the needed values to achieve this or do I have to do it another way?
class NewImage {
private Bitmap image;
private String description;
private String title;
}
You should use a multipart POST request:
Client:
#Rest(rootUrl = "your_url", converters = FormHttpMessageConverter.class)
public interface UploadClient extends RestClientHeaders {
#Post("/Image/{id}")
#RequiresHeader(HttpHeaders.CONTENT_TYPE)
String uploadImage(int id, MultiValueMap<String, Object> data);
}
Usage:
MultiValueMap<String, Object> data = new LinkedMultiValueMap<>();
FileSystemResource image = new FileSystemResource("path_to_image");
String description = "description";
String title = "title";
data.put("image", image);
data.put("description", description);
data.put("title", title);
client.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE);
client.uploadImage(1, data);
I know this has some boilerplate, but it will be improved in the near future.
Reflect for the question in the comment:
You can create a class:
class ObjectSupportingFormHttpMessageConverter extends FormHttpMessageConverter {
public ObjectSupportingFormHttpMessageConverter() {
addPartConverter(new ObjectToStringHttpMessageConverter(new DefaultConversionService()));
}
}
Then use it as a converter. This will convert your objects to text/plain parts. However, maybe it is better to serialize this complex structure into JSON instead of sending it in the multipart post.
Related
Complete base 64 string is not uploding to json request
Actual json request is:
{
"obj":
{
"FarmerName":"abcd",
"IdAgent":"123",
"TPFileUpload":"_9j_4AAQSkZJRgABAQAAAQABAAD_2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFx..............",
"TPFileUploadType":"jpg"
}
}
But From code json request as follows:
{"obj":{"FarmerName":"","
IdAgent":"",
"TPFileUpload":"_9j_4AAQSkZJRgABAQAAAQABAAD_2wBDABALDA4MChAODQ4
Issues are:
1)json is not closed
2)base 64 string of image is not completely uploading to json request.
3)The parameter after "TPFileUpload" are not adding to json request because
of Base 64 encoded string of image.
Service Request as follows:
#Headers("Content-Type: application/json")
#POST("service/saveinput")
Call<SaveInputResponse> saveInput(#Body SaveInput saveinput);
saveInput pojo class:
public class SaveInput {
#SerializedName("obj")
#Expose
private Input obj;
public Input getObj() {
return obj;
}
public void setObj(Input obj) {
this.obj = obj;
}
}
Input class:
public class FooInput {
#SerializedName("FarmerName")
#Expose
private String farmerName;
#SerializedName("IdAgent")
#Expose
private String idAgent;
#SerializedName("TPFileUpload")
#Expose
private String tPFileUpload;
#SerializedName("TPFileUploadType")
#Expose
private String tPFileUploadType;
//Getters and setters of Variables...
}
I have tried the request using retrofit library and also with volley library,but no result,can you please provide suggestion to upload base64 string to json request in android.and some times "/" is replaced by "_"base64 string of request...
Note:base64 encode string is too large i.e,more than 180 lines..
I am also using this. I add my code. May help this.
01. First get your image and convert it base64.
02. Http request with Json format.
[
{
"attachment": "Your base64 String",
"clients": {
"CLIENTS_ID": "18081000000120"
},
"projects": {
"PROJECT_ID": "18081000000306"
},
"userCode": "18011000000027"
}
]
This is my method that is used to send some form data, but i want to send an image also, is this possible using this same method and adding it using an image property in the class or it is more reasonable sending it using another method separatly.
#POST("PostBanderolDataJSON")
Call<ReportPostData> PostData(#Body ReportPostData reportdata);
This is my class:
public class ReportPostData {
private int Id;
private String Banderolnr;
private String Pharmacy;
private String Place;
private String LocationLongitude;
private String LocationLatitude;
}
Use Multi Part
For example
#Multipart
#POST("/v1/upload/sell-image")
Call<CustomerUploadImageResponse> signUp(
#Header(KEY_X_AUTH) String authToken,
#Part List<MultipartBody.Part> signUpDataList
);
To Generate signUpDataList Use like
List<MultipartBody.Part> signUpDataList = new ArrayList<>();
signUpDataList.add(MultipartBody.Part.createFormData("qid", "1333"));
signUpDataList.add(MultipartBody.Part.createFormData("ut", "xyz");
String path = customerImageUploadData.getImageUrl();
Bitmap bitmap = ImageUtil.getBitmap(mActivity, path);
if (null != bitmap) {
MultipartBody.Part part = MultipartBody.Part.createFormData(
"img",
"profile.jpg",
RequestBody.create(null, ImageUtil.getBytesFromBitmapFullQuality(bitmap))
);
signUpDataList.add(part);
}
so I'm trying to send a simple String to my REST server from an Android app using androidannotations.
http://localhost:8080/TestServer_RESTJersey/api/lanceurs/parPays
Using Advanced REST client chrome extension, I send the parameter :
country=Europe
and it's working fine. Now my problem whith the Android app is that my request is received by the server, but the country parameter is always null. My others GET requests are all working perfectly.
Here is my RestClient class :
#Rest(converters = {MappingJacksonHttpMessageConverter.class, FormHttpMessageConverter.class})
public interface RestClient extends RestClientRootUrl, RestClientSupport{
#Get("/poke/simple")
public MessageResponse simplePoke();
#Get("/api/lanceurs/{name}")
public LaunchVehicleResponse nameRequest(String name);
//server doesn't get the parameter here...
#Post("/api/lanceurs/parPays")
public LaunchVehicleResponse countryRequest(String country);
}
Any help would be appreciated as usual, thanks!
EDIT :
server-side REST api :
#Path("api/lanceurs/parPays")
#POST
public String getLanceurByCountry(#FormParam("country") String country)
{
initData();
LaunchVehicleResponse lvr = new LaunchVehicleResponse();
ArrayList<LaunchVehicle> allv = myDatabase.getDataByCountry(country);
lvr.setData(allv);
return parseObjectToJson(lvr);
}
In JAX-RS, use #QueryParam annotation to inject URI query parameter into Java method. example,#QueryParam("country") String countryName,
Try the below, i guess, it should work
#Post("/api/lanceurs/parPays")
public LaunchVehicleResponse countryRequest(#QueryParam("country") String country);
Ok, it seems I figured out a way to get myself out of this mess.
I made a class LaunchVehicleRequest on my client, containing (among other things) a country String. When I need to send a request to my server, I instantiate this class and initialize LaunchVehicleRequest.country with the value I want (ex: "USA"). Then I send the whole object to my RestClient.
LaunchVehicleRequest lvreq = new LaunchVehicleRequest();
lvreq.setCountry("Europe");
LaunchVehicleResponse lvr = pm.countryRequest(lvreq);
...
#Rest(converters = {MappingJacksonHttpMessageConverter.class, FormHttpMessageConverter.class}, interceptors = { LoggingInterceptor.class } )
public interface RestClient extends RestClientRootUrl, RestClientSupport, RestClientHeaders{
#Post("/api/lanceurs/parPays")
public LaunchVehicleResponse countryRequest(LaunchVehicleRequest request);
}
I set up the same class on my server-side, which get the request as a string and then convert it in an object.
#Path("api/lanceurs/parPays")
#POST
public String getLanceurByCountry(String request)
{
// request={"country":"USA"}
//my json parsing function here
LaunchVehicleRequest lvreq = parseJsonToRequest(request);
...
}
I don't know is this is the best way, but hey it's working fine now and I'm using my LaunchVehicleRequest class for every different request I can need to, so it's not THAT bad I guess ^^'
Thanks everyone anyway ;)
As explained on the wiki, you can send form parameters this way:
#Rest(rootUrl = "http://company.com/ajax/services", converters = { FormHttpMessageConverter.class, MappingJackson2HttpMessageConverter.class })
public interface MyRestClient extends RestClientHeaders {
#RequiresHeader(HttpHeaders.CONTENT_TYPE)
#Post("/api/lanceurs/parPays")
public LaunchVehicleResponse countryRequest(MultiValueMap<String, Object> data);
}
MultiValueMap<String, Object> data = new LinkedMultiValueMap<>();
data.set("country, "Europe");
client.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE);
client.countryRequest(data);
I'm developing an Android app that sends requests to a server (rails) through Retrofit.
My current issue is file upload. On server side I have paperclip to handle file upload.
I can't seem to include a TypedFile inside an object which I'd like to send as a parameter
Here is the api method I'm calling, whit its parameters
#Multipart
#POST("/containers/{id}/items")
void addItem(#Path("id") int id,
#Part("item")NewItemData newItemData,
Callback<String> callback);
Basically I want to post this object (containing a TypedFile)
public class NewItemData{
String original_filename;
String content_type;
TypedFile file;
String description;
String location;
int container_id;
...
}
edit:
I forgot to show you how i create the object
public NewItemData(Context context, String file_path){
String mime_type = FileUtilities.getMimeType(file_path);
String[] file_name_parts = file_path.split("/");
String file_name = file_name_parts[file_name_parts.length-1];
this.original_filename = file_name;
this.full_file_path = file_path;
this.content_type = mime_type;
File file_tmp = new File(file_path);
this.file = new TypedFile("application/octet-stream", file_tmp);
this.description = "";
this.location = "";
}
end edit
This is the error that I'm getting:
retrofit.RetrofitError: retrofit.converter.ConversionException: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY at line 1 column 2
And this is the object NewItemData converted to json
{"original_filename":"IMG_20150121_221732.jpg","content_type":"image/jpeg","description":"","file":{},"location":"","container_id":0}
As you can see the "file" field is empty, so I assume that the error above is referring to the fact that "file" => {} instead of the binary file
What I've tried so far hasn't worked, so my questions are:
is possible to post a "wrapper" object in multipart mode?
if so, what annotation should I write and where?
should i implement a custom serializer?
If you need additional info, just ask
Thank you
When you create the restAdapter Instance, just add this line to add a converter .addConverterFactory( GsonConverterFactory.create()) like below
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(RestConnection.BASE_URL_MULTIMEDIA)
.addConverterFactory( GsonConverterFactory.create())
.client(client)
.build();
I am new to android developing, my website returns posts with following format in json:
post= {
'artist':'xxxx',
'title':'xxxx',
'text':'xxxx',
'url':'http://xxxx'
}
I know something about receiving a file from the net and saving it to a SD card, but I want to do it on fly, parse it and show in on some text view, can you please give me some simple code for this?
I tried searching but I can't find a good tutorial for this, so this is the last place I'm coming to solve my problem.
A good framework for parsing XML is Google's GSON.
Basically you could deserialize your XML as follows (import statements left out):
public class Post {
private String artist, title, text, url;
public Post() {} // No args constructor.
}
public class Main {
public static void main(String[] args) {
Gson gson = new Gson();
String jsonString = readFromNetwork(); // Read JSON from network...
Post post = gson.fromJson(jsonString, Post.class);
// Use post instance populated with your JSON data.
}
}
Read more in GSON's user guide.