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