Post an image along some form data Retrofit to WCF Rest - android

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);
}

Related

How can i send complete base 64 string of image to json request android

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"
}
]

Shared prefences inside interface

I'm using retrofit to get and post some data from the server.
I need the URL from the user, so I saved them in shared preferences, I'm able to read the baseurl in the service file from shared preferences, but I can read them in interface 'JsonPlaceHolderApi' as it needs context and another error is of an attribute value must be constant.
First solution is to use url parameters like this:
public interface JsonPlaceholderApi{
#GET("{get_url}")
Call<List<Messages>> getPosts(#Path("get_url") String getUrl);
#FormUrlEncoded
#POST("{post_url}")
Call<List<MessageStatus>> PostStatus(#Path("post_url") String postUrl, ....);
}
and when you want to call your api pass that url like below:
api.getPosts(mPreferences.getString("get_url" , ""))
api.PostStatus(mPreferences.getString("post_url" , ""), ...)
There is also a tricky solution (which I personally hate it) but you can set urls to some constants and manipulate them in your Interceptor (e.g. replacing them) by reading them from shared preferences.
For example:
public interface JsonPlaceholderApi{
public static final String GET_POSTS_DUMMY_URL = "GET_POSTS_DUMMY_URL";
public static final String POST_STATUS_DUMMY_URL = "POST_STATUS_DUMMY_URL";
#GET(GET_POSTS_DUMMY_URL)
Call<List<Messages>> getPosts();
#FormUrlEncoded
#POST(POST_STATUS_URL)
Call<List<MessageStatus>> PostStatus(....);
}
And then in your retrofit Interceptor's intercept function do something like this:
public class RetrofitInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder requestBuilder = request.newBuilder();
// ...
requestBuilder.url(request.url().toString()
.replace(
JsonPlaceholderApi.GET_POSTS_DUMMY_URL,
mPreferences.getString("get_url" , "")
)
.replace(
JsonPlaceholderApi.POST_STATUS_DUMMY_URL,
mPreferences.getString("post_url" , "")
)
);
request = requestBuilder.build();
// ...
return chain.proceed(request);
}
}
And if you don't know how to add interceptor to retrofit check this document
Since the baseUrls are not going to change u can save them statically any where in a separate constants class and get them using the name of the class without using the SharedPreferences
class Consts {
public static final String GET_URL = "put_url_here";
public static final String POST_URL = "put_url_here";
}
then, in the Interface where u need any of them just place:
Consts.GET_URL
or
Consts.POST_URL

Saving an Object containing Bitmap

I'm working on an android application (first application-beginner) and I'm trying to save data when the app closes to load again.
The data I want to store is a list of books, and each book contains info (author, date, etc) and a bitmap containing the book's picture. I tried using GSON to convert the list to JSON and store in SharedPreferences but that caused problems because of the bitmap.
How should I save the file and retrieve it again when the app launches ?
This is a brief version of the code
Library Class
public class Library {
private ArrayList<Entry> library ;
public Library () {
library = new ArrayList<Entry>();
}
public void addEntry( Entry entry ) {
library.add(entry);
}
public void removeEntry ( Entry entry ) {
if (library.contains(entry))
library.remove(entry);
else Log.d ( "Library" , "Entry Not Found");
}
public ArrayList<Entry> getLibrary() {
return library;
}
#Override
public String toString() {
return "Library{" +
"library=" + library +
'}';
}
}
Entry Class
public class Entry {
Book book ;
final LocalDate borrowDate;
LocalDate dueDate;
//some methods for application
}
Book Class
public class Book implements Parcelable {
private String title;
private String author;
private String isbn ;
private double rating;
private int ratingCount;
private int pageCount;
private transient Bitmap image;
private String overview;
//some methods
}
Don't put the bitmap in sharedpreferences. Save it in file.
If you need to persist the bitmap, you can assign it to a static field.
You can also convert it to a 64 bit String.. but that is bad design (and I think it is a very slow and expensive operation!):
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos); //bm is the bitmap object
byte[] b = baos.toByteArray();
String encoded = Base64.encodeToString(b, Base64.DEFAULT);
^ Save that to SharedPreferece. Now to decode:
byte[] imageAsBytes = Base64.decode(encoded.getBytes());
ImageView image = (ImageView)this.findViewById(R.id.ImageView);
image.setImageBitmap(BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length));
Use Picasso and load the urls directly instead of downloading and saving as bitmap
Picasso.with(mContext)
.load("imageURL here")
.placeholder(R.drawable.default_pic)
.error(R.drawable.error_pic)
.resizeDimen(100, 100)
.centerCrop()
.into(holderOrderHistory.mIcon);

Sending images with AndroidAnnotations RestService

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.

TypedFile inside object using Retrofit on Android

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();

Categories

Resources