Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am trying to do this Post request on retrofit
First of call create Interface for your POST API
public interface APIInterface {
#Multipart
#POST("you_api_node")
Call<MediaTransfer> PostMedia(#Part("key") RequestBody key,
#Part("AwsAccesskeyID") RequestBody AwsAccesskeyID,
#Part("x-amz-security-token") RequestBody x-amz-security-token,
#Part("policy") RequestBody policy,
#Part("signature") RequestBody signature,
#Part MultipartBody.Part file);
}
Your API Client Class where you have intitializae your Retrofit
public class APIClient {
public static Retrofit retrofit;
public static Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Gson gson = new GsonBuilder()
.setLenient()
.create();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl("http://mybaseurl.com")
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
}
return retrofit;
}
}
Now in create PostMedia funtion in your Activity/Class
public void PostMedia(RequestBody key,RequestBody AwsAccessKeyID,RequestBody x-amz-security-token, RequestBody policy, RequestBody signature,MultipartBody.Part file ){
APIInterface apiInterface = APIClient.getClient().create(APIInterface.class);
Call<MediaTransfer> call = apiInterface.PostMedia(key, AwsAccessKeyID, x-amz-security-token, policy, signature,file);
call.enqueue(new Callback<MediaTransfer>() {
#Override
public void onResponse(Call<MediaTransfer> call, Response<MediaTransfer> response) {
if (response.isSuccessful()) {
//Do Something
}
}
#Override
public void onFailure(Call<MediaTransfer> call, Throwable t) {
mediaTimeout = t.getMessage();
Log.d("MyResponse", "Post Media failure" + t.getMessage());
}
});
}
Now in your MainActivity you can call.
File myfile = new File(filePath);
RequestBody surveyBody = RequestBody.create(MediaType.parse("image/*"), file);
surveyImagesParts[index] = MultipartBody.Part.createFormData("file", file.getName(), surveyBody);
RequestBody key= RequestBody.create(MediaType.parse("multipart/form-data"), key);
RequestBody AwsAccesskeyID= RequestBody.create(MediaType.parse("multipart/form-data"), AwsAccesskeyID);
RequestBody x-amz-security-token = RequestBody.create(MediaType.parse("multipart/form-data"), x-amz-security-token);
RequestBody policy= RequestBody.create(MediaType.parse("multipart/form-data"), policy);
RequestBody signature= RequestBody.create(MediaType.parse("multipart/form-data"), signature);
Now you can call above PostMedia(...) function.
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:
enter image description here
I'm new the Android developer, I'm working on an application, I have activity is users can upload their items to the server (the text and image), but the problem is upload text is easy , I used Volley to upload the text to server, but I struggle long time to upload the multiple the images to server. I saw the Retrofit 2 really good for multiple file upload but I have A lot problems.
I tried a lot but to no avail and I tried to share one of the codes with you so you can help me.
I also use bearer tokens but I don't know it is correct or not.
File file1 = new File(patch_img1);
File file2 = new File(patch_img2);
File file3 = new File(patch_img3);
RequestBody image1 = RequestBody.create(MediaType.parse("image/*"),
file1);
RequestBody image2 = RequestBody.create(MediaType.parse("image/*"),
file2);
RequestBody image3 = RequestBody.create(MediaType.parse("image/*"),
file3);
RequestBody invoice = RequestBody.create(MediaType.parse("text/plain"), invoices);
UserSharedPref sharedPref = new UserSharedPref(CompletedServiceActivity.this);
WebServicesAPI request = APIClient.getApiClient("https://text.com/api/").create(WebServicesAPI.class);
Call<ResponseBody> call = request.upload(sharedPref.getUserToken(),image1,image2,image3,invoice);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
my interface.class
#POST("invoices")
Call<ResponseBody> upload(
#Header("Authorization") String authorization,
#Part("image1") RequestBody image1,
#Part("image2") RequestBody image2,
#Part("image3") RequestBody image3,
#Part("invoice") RequestBody invoice
);
APIClient.class
public class APIClient {
public static Retrofit retrofit = null;
public static Retrofit getApiClient(String url) {
if (retrofit == null) {
Gson gson = new GsonBuilder()
.setLenient()
.create();
retrofit = new Retrofit.Builder().baseUrl(url)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
}
Try this it's work with me :
String path3 = image3.getPath();
File file3 = new File(path3);
// Parsing any Media type file
RequestBody requestBody3 = RequestBody.create(MediaType.parse("*/*"), file3);
MultipartBody.Part fileToUpload3 = MultipartBody.Part.createFormData("filename", file3.getName(), requestBody3);
RequestBody filename3 = RequestBody.create(MediaType.parse("text/plain"), image3.getName());
Calling method:
UploadImage3(fileToUpload3,filename3);
Interface:
#POST("uploadimage3.php")
#Multipart()
Observable<ApiResponse>UploadImage3(#Part MultipartBody.Part file, #Part("filename") RequestBody name);
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 want to send some data with retrofit including an image and three strings,
how should my WCF server side method signature be to handle these posted data if someone could help me?
The below code is my client side with retrofit(although im not sure it is well written).
#Multipart
#POST("PostBanderolDataJSON")
Call<MyResponse> PostData(#Part("banderolNr") RequestBody banderolNr, #Part("pharmacy") RequestBody pharmacy, #Part("place") RequestBody place, #Part("report_pic\"; filename=\"rp.png\" ") RequestBody file);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(RetrofitApiInterface.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitApiInterface api = retrofit.create(RetrofitApiInterface.class);
RequestBody reportImage = RequestBody.create(MediaType.parse("image/jpeg"), ImagePath);
RequestBody banderoNr = RequestBody.create(MediaType.parse("text/plain"), etBanderolNr.getText().toString());
RequestBody pharmacy = RequestBody.create(MediaType.parse("text/plain"), Pharmacy.getText().toString());
RequestBody place = RequestBody.create(MediaType.parse("text/plain"), Place.getText().toString());
Call<MyResponse> call = api.PostData(banderoNr,pharmacy,place,reportImage);
call.enqueue(new Callback<MyResponse>() {
#Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
if (response.isSuccessful()) {
if (!response.body().error) {
Toast.makeText(getApplicationContext(), "Data Sent Successfully...", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Some error occurred...", Toast.LENGTH_LONG).show();
}
progress.dismiss();
}
else{
Toast.makeText(getApplicationContext(),"Something went wrong with the request to the server !",Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<MyResponse> call, Throwable t) {
progress.dismiss();
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
I am doing android, looking for a way to do a super basic http GET/POST request. I keep getting an error:
java.lang.IllegalArgumentException: Unable to create converter for class java.lang.String
Webservice:
public interface WebService {
#GET("/projects")
Call<String> jquery();
}
then in my java:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://jquery.org")
// .addConverterFactory(GsonConverterFactory.create())
.build();
WebService service = retrofit.create(WebService.class);
Call<String> signin = service.jquery();
Toast.makeText(this, signin.toString(), Toast.LENGTH_LONG).show();
I'm literally just trying to query jquery.org/projects with a GET request and return the String that it responds with. What is wrong?
If I try to implement a custom Converter (I've found a few examples online) it complains that I didn't implement the abstract method convert(F), which none of the examples do.
Thanks.
Add Retrofit2 and ScalarsConverterFactory to your Retrofit.Builder.
adapterBuilder = new Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create());
To use ScalarsCoverter add following dependency to your build graddle
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0' //Adding Retrofit2
For API Call use:
Call <String> *****
Android Code :
.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
Log.i("Response", response.body().toString());
//Toast.makeText()
if (response.isSuccessful()){
if (response.body() != null){
Log.i("onSuccess", response.body().toString());
}else{
Log.i("onEmptyResponse", "Returned empty response");//Toast.makeText(getContext(),"Nothing returned",Toast.LENGTH_LONG).show();
}
}
I take a look at Retrofit library and noticed that it parses response according to the type class inside Call<T>. So you have two option:
1st: create a class according to the response from the server.
2nd: get the response and handle it yourself (Not recommended Retrofit already handles it. So why do you use Retrofit as it is tailored for this job). Anyway instead of Call<String> use Call<ResponseBody> and Call<ResponseBody> signin = service.jquery(); after this put the following
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {
// handle success
String result = response.body().string();
}
#Override
public void onFailure(Throwable t) {
// handle failure
}
});
To get the response as a String, you have to write a converter and pass it when initializing Retrofit.
Here are the steps.
Initializing retrofit.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL_BASE)
.addConverterFactory(new ToStringConverterFactory())
.build();
return retrofit.create(serviceClass);
Converter class for converting Retrofit's ResponseBody to String
public class ToStringConverterFactory extends Converter.Factory {
private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain");
#Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
if (String.class.equals(type)) {
return new Converter<ResponseBody, String>() {
#Override
public String convert(ResponseBody value) throws IOException
{
return value.string();
}
};
}
return null;
}
#Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations,
Annotation[] methodAnnotations, Retrofit retrofit) {
if (String.class.equals(type)) {
return new Converter<String, RequestBody>() {
#Override
public RequestBody convert(String value) throws IOException {
return RequestBody.create(MEDIA_TYPE, value);
}
};
}
return null;
}
}
And after executing service.jquery();, signin will contain JSON response.
You can try the following:
build.gradle file:
dependencies {
...
compile 'com.squareup.retrofit2:retrofit:2.0.1'
...
}
WebAPIService:
#GET("/api/values")
Call<String> getValues();
Activity file:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL_BASE)
.build();
WebAPIService service = retrofit.create(WebAPIService.class);
Call<String> stringCall = service.getValues();
stringCall.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
Log.i(LOG_TAG, response.body());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(LOG_TAG, t.getMessage());
}
});
I have tested with my Web serivce (ASP.Net WebAPI):
public class ValuesController : ApiController
{
public string Get()
{
return "value1";
}
}
Android Logcat out: 04-11 15:17:05.316 23097-23097/com.example.multipartretrofit I/AsyncRetrofit2: value1
Hope it helps!
call.enqueue(new Callback<Object>() {
#Override
public void onResponse(#NonNull Call<Object> call, #NonNull Response<Object> response) {
if (response.isSuccessful()) {
Gson gson = new Gson();
String successResponse = gson.toJson(response.body());
Log.d(LOG_TAG, "successResponse: " + successResponse);
} else {
try {
if (null != response.errorBody()) {
String errorResponse = response.errorBody().string();
Log.d(LOG_TAG, "errorResponse: " + errorResponse);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(#NonNull Call<Object> call, #NonNull Throwable t) {
}
});
Just use log level BODY in intercepror:
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()....
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
clientBuilder.addNetworkInterceptor(httpLoggingInterceptor);
And you can see body in logcat like:
D/OkHttp: {"blablabla":1,.... }
D/OkHttp: <-- END HTTP (1756-byte body)
This solution for debug only, not for get String directly in code.
thought it might be late to answer just use response.body()?.string() and you'll have your response as a string.
I change the Response type, instead of adding ScalarsConverterFactory like this
interface YourApiService {
#GET("/endpoint")
fun getResponse(): Call<ResponseBody>
}
And then you can get the string object by
val str = response.body().toString()
String body = new String(((TypedByteArray) response.getBody()).getBytes());
if you found
java.lang.ClassCastException: retrofit.client.UrlConnectionClient$TypedInputStream cannot be cast to retrofit.mime.TypedByteArray
then put this in your RestAdapter
.setLogLevel(RestAdapter.LogLevel.FULL)
for Example:
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(Root_url)
.build();