Retrofit2: How to get binary file inside response body - java

I get data from a web service that sends files in binary format inside response body. I want to get that binary data.
I'm not gonna write the whole log here because it's too long and it's not helpful but i'm gonna write the first few lines:
The first line of the PDF is this: %PDF-1.4 and the rest is binary characters like this: ��Yi3y�H�w��L�A���mCv��.��K��7����Z0�VP. so it's a PDF file inside response body.
And here's my code to get it:
#Streaming
#Headers({"Content-Type: application/json", "Accept: application/json"})
#POST("/auto/report/download")
Call<String> sendStatementDownloadRequest(#Body DepositStatementsDownloadRequest request);
And this is how i call it:
webservice.sendStatementDownloadRequest(request).enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful()) {
Log.i("VVV", "onResponse: " + new Gson().toJson(response));
} else {
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
}
});
The problem is it only gets the first line which is this: %PDF-1.4 and skip the rest of it which is the binary data.
is there anyway to get the whole body?

Call for a ResponseBody object instead of String
Your call should be like this
#Streaming
#Headers({"Content-Type: application/json", "Accept: application/json"})
#POST("/auto/report/download")
Call<ResponseBody> sendStatementDownloadRequest(#Body DepositStatementsDownloadRequest request);

Related

How to upload video file with extra string values in body, using Retrofit in Java?

I have to upload video file to Server using API, I am using Retrofit. I tried Multipart (by using different approaches) but failed.
I have to upload a video file, reference key as a string and url as a string (in body). In header, I have to upload token.
First I tried this:
Interace:
#Multipart
#POST(url)
Call<LivenessRequest> requestFun(#Header("Authorization") String token,
#Part("reference") RequestBody referenceId,
#Part("url") RequestBody url,
#Part("file") RequestBody videoFile);
Making RequestBody Objects:
RequestBody fileBody;
RequestBody referenceBody;
RequestBody urlBody;
fileBody = RequestBody.create(okhttp3.MediaType.parse("video/*"), videoFile);
referenceBody = RequestBody.create(okhttp3.MediaType.parse("text/plain"), String.valueOf(
"refernce_id_here"));
urlBody = RequestBody.create(okhttp3.MediaType.parse("text/plain"), String.valueOf(
"www.google.com"));
calling API:
interface().requestFun(token,
referenceBody, urlBody, videoFileBody).enqueue(new retrofit2.Callback<request>() {
#Override
public void onResponse(retrofit2.Call<request> call, Response<request> response) {
}
#Override
public void onFailure(retrofit2.Call<request> call, Throwable t) {
}
});
I tried it with another approach that is:
Interface:
#Multipart
#POST(url)
Call<LivenessRequest> requestFun(#Header("Authorization") String token,
#Body RequestBody body);
Making RequestBody Object:
RequestBody body = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file",videoFile.getName(),
RequestBody.create(MediaType.parse("application/octet-stream"), videoFile))
.addFormDataPart("url","www.google.com")
.addFormDataPart("reference", reference)
.build();
API calling:
interface().requestFun(token, body).enqueue(new retrofit2.Callback<request>() {
#Override
public void onResponse(retrofit2.Call<request> call, Response<request> response) {
}
#Override
public void onFailure(retrofit2.Call<request> call, Throwable t) {
}
});
Postman Screenshot of this api is attached:

Retrofit Post Multipart form data values are empty

I am trying to post some multipart form data via Retrofit in Android to a web service.
The web services's API expects the following parameters to be passed as field of a multipart form data:
Name Type
company_id text/plain
image image/*
It also expects an authorization token to be passed as a query string parameter.
So i have defined my API interface call like this:
#Multipart
#POST("/companies/uploadImage")
#Headers({
"Content-Type: multipart/form-data",
"Accept: application/json"
})
Call<ServerResponse> companyUploadImage( #Part("company_id") RequestBody companyId, #Part MultipartBody.Part file, #Query("token") String token);
Afterwards this is how i call the above API interface method in a custom class:
RequestBody companyId = RequestBody.create(MediaType.parse("text/plain"), LocalStorage.getInstance().getCompanyId());
File file = new File(postPath);
MultipartBody.Part image = MultipartBody.Part.createFormData("image", file.getName(), RequestBody.create(MediaType.parse("image/*"), file));
Call<ServerResponse> uploadProfileImage = router.companyUploadImage(companyId, image, token);
uploadProfileImage.enqueue(new Callback<ServerResponse>() {
#Override
public void onResponse(Call<ServerResponse> call, Response<ServerResponse> response) {
Log.e("Upload Profile Image: ", response.body().getMessage());
}
#Override
public void onFailure(Call<ServerResponse> call, Throwable t) {
Log.e("Upload Profile Image Error: ", t.getMessage());
}
});
The request is sent successfully to the server, so no networking exceptions occur, however the multipart form values, company_id and image, are received empty on the server side
Any idea?
Thank you!
I managed to solve the issue. It seems that the solution was as simple as removing the #Header annotation from the API interface method. So now it looks like this:
#Multipart
#POST("/companies/uploadImage")
Call<ServerResponse> companyUploadImage( #Part("company_id") RequestBody companyId, #Part MultipartBody.Part file, #Query("token") String token);
Maybe someone will find this post helpful.

Call Retrofit without having Value

how to call Retrofit GET method api in which no value will pass in GET(")
this is my code
#GET(" ")
fun fetchData(): Call<List<Data>>
this is my BASE URL https://abhi-debug.github.io/Caption/All
and it cant have backslash at end
#GET(".")
fun fetchData(): Call<List<Data>>
Pass "." as the parameter
My suggestion would be to have a base URL like: https://abhi-debug.github.io/
And then add this:
#GET("Caption/All")
fun fetchData(): Call<List<Data>>
Solution 1
You can use #GET(".") to indicate that your url is the same as the base url.
#GET(".")
Call<List<Data>> fetchData();
Solution 2
You can pass URL to reuest as you mention you got URL in json response
#GET()
Call<List<Data>> fetchData(#Url String url);
and call
Call<List<Data>> call = retrofitInterface.fetchData("https://abhi-debug.github.io/Caption/All");
call.enqueue(new Callback<List<Data>>() {
#Override
public void onResponse(Call<List<Data>> call, Response<List<Data>> response) {
Log.i(TAG, response.body().toString());
List<Data> body = response.body();
Log.i(TAG, body.get(0).getId()+"");
}
#Override
public void onFailure(Call<List<Data>> call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
In your Api Interface use this method
#GET
Call<JsonObject> fetchData(#Url String config);

Error in sending large file with retrofit multipart POST request

i'm using retrofit2 library for post data to server, I need to upload a file or photo with POST request and get it's response. So i have two ways:
Encoding the file to base64 and sending it as a text in post body.
Using Multi part request and sending the file directly .
And i tried them, but in both ways, i have same problem:
when I send small files (for example under 500 bytes),I get successful result.
But the problem occurs when i send a large file. I get nothing until the timeout finishes, in AVD I get successful response (Also in Postman), but in real devices (HTC with android 5.1 & Samsung S6 with Android 7.0) the below error occurs:
java.io.IOException: unexpected end of stream on Connection{myIp:port, proxy=DIRECT# hostAddress=/myIp:port cipherSuite=none protocol=http/1.1
Call Method:
#Multipart
#POST("uploaddata")
Call<ResponseBody> uploaddate(#Part("file") RequestBody filePart, #Part("token") RequestBody token,
#Part("type") RequestBody type, #Part("name")RequestBody name);
Main method:
public void uploadImage(String type, File file, String name, String token, final DataInterface listener) {
RequestBody filePart = RequestBody.create(MediaType.parse("image/*"), file);
RequestBody tokenPart = RequestBody.create(MediaType.parse("text/plain"), token);
RequestBody namePart = RequestBody.create(MediaType.parse("text/plain"), name);
RequestBody typePart = RequestBody.create(MediaType.parse("text/plain"), type);
Call<ResponseBody> uploadData = apiInterface.uploaddate(filePart, tokenPart, typePart, namePart);
uploadData.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
listener.onResponseListener(response.body());
} else {
Log.e(TAG, "uploadData -----> response.isSuccessful == false");
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e(TAG, "uploadData onFailure -----> " + t);
}
});
}
Can you post the log output of your error
Did it return anything like a large binary data ??
Try this:
#Multipart
#POST("uploaddata")
Call<ResponseBody> uploaddate(#Part MultiPart.Body filePart,
#Part("token") RequestBody token,
#Part("type") RequestBody type,
#Part("name")RequestBody name);
Main method:
public void uploadImage(String type, File file, String name, String token,
final DataInterface listener) {
RequestBody filePart = RequestBody.create(MediaType.parse("image/*"), file);
MultiPartBody.Part body = MultiPartBody.Part.createFormData("filePart",file.getName(),filePart);
RequestBody tokenPart = RequestBody.create(MediaType.parse("text/plain"), token);
RequestBody namePart = RequestBody.create(MediaType.parse("text/plain"), name);
RequestBody typePart = RequestBody.create(MediaType.parse("text/plain"), type);
Call<ResponseBody> uploadData = apiInterface.uploaddate(body, tokenPart, typePart, namePart);
uploadData.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
listener.onResponseListener(response.body());
} else {
Log.e(TAG, "uploadData -----> response.isSuccessful == false");
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e(TAG, "uploadData onFailure -----> " + t);
}
});
}

How do you access a method of object in Retrofit Response<List<Object>>

I was able to accomplish the goal of calling a method from the object class in this instance:
#Override
public void onResponse(Call<ServerResponse> call, retrofit2.Response<ServerResponse> response) {
ServerResponse resp = response.body();
if(resp.getResult().equals(Constants.SUCCESS)){
progress.setVisibility(View.GONE);
tv_message.setVisibility(View.GONE);
dialog.dismiss();
Snackbar.make(getView(), resp.getMessage(), Snackbar.LENGTH_LONG).show();
}else {
progress.setVisibility(View.GONE);
tv_message.setVisibility(View.VISIBLE);
tv_message.setText(resp.getMessage());
}
}
but in the problem instance, the response is a List of ServerResponse objects. so when I try to do the following:
#Override
public void onResponse(Call<List<ServerResponse>> call, Response<List<ServerResponse>> response) {
List<ServerResponse> resp = response.body();
if(resp.getResult().equals(Constants.FAILURE)){
tv_noResponses.setText(resp.getMessage());
progressBar.setVisibility(View.INVISIBLE);
}else {
replyList = (ArrayList<ServerResponse>) response.body();
Collections.reverse(replyList);
progressBar.setVisibility(View.INVISIBLE);
mAdapter = new ReplyRecyclerAdapter(replyList, getActivity());
recyclerView.setAdapter(mAdapter);
}
}
the methods "getResult()" and "getMessage()" of course aren't available through the List interface, what do I have to do to make them available?
getResult() and getMessage() are methods in the ServerResponse class which are used to provide you with a result of your request as your preferences.
in your first request, you are expecting a server response to parse it into a ServerRespons object.but in the second request you are expecting a list of sth.
As I can Understand from your code. you are trying to retrieve a list of something (list of replays) to populate it inside the RecyclerView.
you don't need getResult() and getMessage() here. just make a
List<YourModelOfRecyclerView>. if sth went wrong with your request onError() will be called.
you can also modify your JSON response to add a custom server response with the list.and you will no longer need ServerResponse but a new Model that wraps your custom response and the list.

Categories

Resources