I am trying to upload a file using multipart request in okhttp.
using below code.
public static Boolean uploadFile(String serverURL, File file) {
try {
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("text/csv"), file))
.addFormDataPart("some-field", "some-value")
.build();
Request request = new Request.Builder()
.url(serverURL)
.post(requestBody)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
// Handle the error
}
#Override
public void onResponse(Response response) throws IOException {
if (!response.isSuccessful()) {
// Handle the error
}
// Upload successful
}
});
return true;
} catch (Exception ex) {
// Handle the error
}
return false;
}
which is working file.
My problem is- i also wants to send some key value pair in body parameters but it is creating problem in request.
I am using below code to append key value body parameters in multipart request.
FormBody.Builder formBodyBuilder = new FormBody.Builder();
formBodyBuilder.add("name", "Mac");
requestBody.addPart(formBodyBuilder.build());
but it is creating problem.
Any help will really appreciated. Thanks
I am doing this with Okhttp3 and it works fine:
MediaType MEDIA_TYPE = MediaType.parse(MIME_TYPE);
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("type", stringsToPost[0])
...
.addFormDataPart("file", file.getName(), RequestBody.create(MEDIA_TYPE, file));
you try this
RequestBody formBody = new FormBody.Builder()
.add("grant_type", "")
.add("username", "")
.add("password", "")
.build();
RequestBody requestBodyy = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addPart(
Headers.of("content-type", "form-data; name=\"image\""),
RequestBody.create(null, "Square Logo"))
.addPart(
Headers.of("content-type", "application/json; charset=utf-8"),
formBody)
.build();
Related
I'm trying to upload images from my android apk.
I use this code, seems works, but I getting no data response
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
okhttp3.RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("image", getBase64Image(bitmapImage))
.build();
okhttp3.Request request = new okhttp3.Request.Builder()
.url("https://api.imgur.com/3/image")
.method("POST", body)
.addHeader("Authorization", "Client-ID " + CLIENT_ID)
.build();
client.newCall(request).enqueue(new okhttp3.Callback() {
#Override
public void onFailure(okhttp3.Call call, IOException e) {
Log.d("ERROR",e.getMessage());
}
#Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
//My code
}
});
I have 500 internal server error, every time when i try to send POST request via Retrofit. When i sending GET request, it sending correctly. I'm sure that with serverside everyting is ok. What's wrong with my code ?
Here is my request method
#POST("/listing/createListing")
Call<ResponseBody> pushData(#Body RequestBody image);
post implementation modelTask is my model class object and firebaseToken is firebase authentication token. In my model class, I am saving images as a file list.
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new
Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws
IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Authorization", "Bearer " +
firebaseToken)
.build();
return chain.proceed(newRequest);
}
}).build();
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl("https://something.herokuapp.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiEndPoint apiService = retrofit.create(ApiEndPoint.class);
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
builder.addFormDataPart("title", modelTask.getTitle());
builder.addFormDataPart("description", modelTask.getDescription());
builder.addFormDataPart("user_name", "Josim Uddin");
builder.addFormDataPart("user_id", "2133323");
builder.addFormDataPart("price", "30.0");
builder.addFormDataPart("category_name", "Cleaning");
builder.addFormDataPart("category_id", "123");
builder.addFormDataPart("preferred_date",
modelTask.getPreferred_date());
builder.addFormDataPart("preferred_time",
modelTask.getPreferred_time());
builder.addFormDataPart("hasPet", modelTask.getHasPet());
builder.addFormDataPart("budget",
String.valueOf(modelTask.getBudget()));
builder.addFormDataPart("address", modelTask.getAddress());
builder.addFormDataPart("longitude",
String.valueOf(modelTask.getLongitude()));
builder.addFormDataPart("latitude",
String.valueOf(modelTask.getLatitude()));
builder.addFormDataPart("equipment", modelTask.getEquipment());
for (int i = 0; i < modelTask.getImages().size(); i++) {
builder.addFormDataPart("image[]",
modelTask.getImages().get(i).getName(),
RequestBody.create(MediaType.parse("multipart/form-data"),
modelTask.getImages().get(i)));
}
MultipartBody requestBody = builder.build();
Call<ResponseBody> call = apiService.pushData(requestBody);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
Log.d(TAG, "onResponse:" + response.code()+",
"+response.message());
if (response.isSuccessful()) {
try {
Log.d(TAG, "post submitted code:" +
response.code()+"body:"+response.body().string());
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e(TAG, "Unable to submit post to API::
"+t.getMessage());
}
});
Postman test is successful.
Try this
#POST("listing/createListing")
Call<ResponseBody> pushData(#Body RequestBody image);
Remove "/" from the link and add it to the end of Base Url.
I am Trying to send audio file using Retrofit but ResponseBody always null and Status is 500 internal server error ,I tried a lot of different things but nothing Works
Postman Screenshots:
body
header
My Client:
public class AudioClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(Context context) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(context.getString(R.string.base_url)).client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
addAudioComment method:
#Multipart
#POST("api/Comment/AddSoundComment")
Call<AudioComment> addAudioComment(#Header("Authorization") String contentRange,
#Part("referenceType") RequestBody ReferenceType,
#Part("referenceId") RequestBody ReferenceID,
#Part("parentId") RequestBody ParentID,
#Part MultipartBody.Part AudioComment);
The Request :
File audioFile = new File(mRecordedFilePath);
RequestBody reqFile = RequestBody.create(MediaType.parse("audio/*"), audioFile);
audioPart = MultipartBody.Part.createFormData("AudioComment", audioFile.getName(), reqFile);
Call<AudioComment> apiCall = service.addAudioComment(String.valueOf(SharedPreferencesHelper.getLogInToken(CommentsActivity.this)),
reqRefType, reqRefId, reqParentId, audioPart);
//apiCall =service.addAudioComment();
apiCall.enqueue(new Callback<AudioComment>() {
#Override
public void onResponse(Call<AudioComment> call, Response<AudioComment> response) {
Log.i("RETROFIT", "onResponse Called");
AudioComment postResult = response.body();
}
#Override
public void onFailure(Call<AudioComment> call, Throwable t) {
String err = t.getMessage() == null ? "" : t.getMessage();
showError(R.string.service_failure);
Log.e("RETROFIT", err);
setRefreshing(false);
dismissProgress();
}
});
In my case I remove #Multipart from interface and replaced
#part with #Body RequestBody requestBody. Eg. as follows,the second parameter is audio file.
public interface APIInterface {
#POST(url)
Call<String> postAudioAndGetResponse(#Header("Subscription-Key") String keyValue,
#Body RequestBody requestBody,
#Query("language") String language);
}
and called above method like this
File file = new File(audioFileName);
RequestBody requestBody = RequestBody.create(MediaType.parse("audio/*"), file);
Call<String> str = apiInterface.postAudioAndGetResponse(speechSubscriptionKey, requestBody,"en-IN");
and it worked .
Hope it will help someone. :)
I'm facing a different Api Service which I have to request using POST but with no body content, I'm sending a image converted to base64, I've been searching about that issue and I found this "solution", which it didn't work :
1 :
RequestBody reqbody = RequestBody.create(null, new byte[0]);
Request.Builder formBody = new Request.Builder().url(url).method("POST",reqbody).header("Content-Length", "0");
2 :
request = new Request.Builder()
.url(BASE_URL + route)
.method("POST", RequestBody.create(null, new byte[0]))
.post(requestBody)
.build();
Even I explicit saying that is a POST method, it keeps send a GET request and not a POST request. Thanks!
My Activity :
public String SendImage(String image64) throws IOException{
//RequestBody reqbody = RequestBody.create(null, new byte[0]);
Request request = new Request.Builder()
.url("http://ap.imagensbrasil.org/api/1/upload/?key=9c9dfe77cd3bdbaa7220c6bbaf7452e7&source=" + image64 + "&format=txt")
.method("POST", RequestBody.create(null, new byte[0]))
.header("Content-Length", "0")
.build();
OkHttpClient Client = client.newBuilder() .readTimeout(25, TimeUnit.SECONDS).build();
Response response = Client.newCall(request).execute();
return response.body().string();
}
It is working on retrofit , so if you continue with Retrofit v2.0 you can use this :
public class Base64EncodeRequestInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request.Builder builder = originalRequest.newBuilder();
if (originalRequest.method().equalsIgnoreCase(POST)) {
builder = originalRequest.newBuilder()
.method(originalRequest.method(), encode(originalRequest.body()));
}
return chain.proceed(builder.build());
}
private RequestBody encode(RequestBody body) {
return new RequestBody() {
#Override
public MediaType contentType() {
return body.contentType();
}
#Override
public void writeTo(BufferedSink sink) throws IOException {
Buffer buffer = new Buffer();
body.writeTo(buffer);
byte[] encoded = Base64.encode(buffer.readByteArray(), Base64.DEFAULT);
sink.write(encoded);
buffer.close();
sink.close();
}
};
}
}
I have this interceptor that i add to my OkHttp client:
public class RequestTokenInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// Here where we'll try to refresh token.
// with an retrofit call
// After we succeed we'll proceed our request
Response response = chain.proceed(request);
return response;
}
}
How can i add headers to request in my interceptor?
I tried this but i am making mistake and i lose my request when creating new request:
public class RequestTokenInterceptor implements Interceptor {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
Request newRequest;
try {
Log.d("addHeader", "Before");
String token = TokenProvider.getInstance(mContext).getToken();
newRequest = request.newBuilder()
.addHeader(HeadersContract.HEADER_AUTHONRIZATION, O_AUTH_AUTHENTICATION + token)
.addHeader(HeadersContract.HEADER_CLIENT_ID, CLIENT_ID)
.build();
} catch (Exception e) {
Log.d("addHeader", "Error");
e.printStackTrace();
return chain.proceed(request);
}
Log.d("addHeader", "after");
return chain.proceed(newRequest);
}
}
Note that, i know i can add header when creating request like this:
Request request = new Request.Builder()
.url("https://api.github.com/repos/square/okhttp/issues")
.header("User-Agent", "OkHttp Headers.java")
.addHeader("Accept", "application/json; q=0.5")
.addHeader("Accept", "application/vnd.github.v3+json")
.build();
But it doesn't fit my needs. I need it in interceptor.
Finally, I added the headers this way:
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
Request newRequest;
newRequest = request.newBuilder()
.addHeader(HeadersContract.HEADER_AUTHONRIZATION, O_AUTH_AUTHENTICATION)
.addHeader(HeadersContract.HEADER_X_CLIENT_ID, CLIENT_ID)
.build();
return chain.proceed(newRequest);
}
you can do it this way
private String GET(String url, Map<String, String> header) throws IOException {
Headers headerbuild = Headers.of(header);
Request request = new Request.Builder().url(url).headers(headerbuild).
build();
Response response = client.newCall(request).execute();
return response.body().string();
}
here is a useful gist from lfmingo
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("User-Agent", "Your-App-Name")
.header("Accept", "application/vnd.yourapi.v1.full+json")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
}
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
Faced similar issue with other samples, this Kotlin class worked for me
import okhttp3.Interceptor
import okhttp3.Response
class CustomInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain) : Response {
val request = chain.request().newBuilder()
.header("x-custom-header", "my-value")
.build()
return chain.proceed(request)
}
}
If you are using Retrofit library then you can directly pass header to api request using #Header annotation without use of Interceptor. Here is example that shows how to add header to Retrofit api request.
#POST(apiURL)
void methodName(
#Header(HeadersContract.HEADER_AUTHONRIZATION) String token,
#Header(HeadersContract.HEADER_CLIENT_ID) String token,
#Body TypedInput body,
Callback<String> callback);
Hope it helps!
There is yet an another way to add interceptors in your OkHttp3 (latest version as of now) , that is you add the interceptors to your Okhttp builder
okhttpBuilder.networkInterceptors().add(chain -> {
//todo add headers etc to your AuthorisedRequest
return chain.proceed(yourAuthorisedRequest);
});
and finally build your okHttpClient from this builder
OkHttpClient client = builder.build();
Kotlin version:
fun okHttpClientFactory(): OkHttpClient {
return OkHttpClient().newBuilder()
.addInterceptor { chain ->
chain.request().newBuilder()
.addHeader(HEADER_AUTHONRIZATION, O_AUTH_AUTHENTICATION)
.build()
.let(chain::proceed)
}
.build()
}
This worked for me:
class JSONHeaderInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain) : Response {
val request = chain.request().newBuilder()
.header("Content-Type", "application/json")
.build()
return chain.proceed(request)
}
}
fun provideHttpClient(): OkHttpClient {
val okHttpClientBuilder = OkHttpClient.Builder()
okHttpClientBuilder.addInterceptor(JSONHeaderInterceptor())
return okHttpClientBuilder.build()
}
package com.example.network.interceptors;
import androidx.annotation.NonNull;
import java.io.IOException;
import java.util.Map;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class RequestHeadersNetworkInterceptor implements Interceptor {
private final Map<String, String> headers;
public RequestHeadersNetworkInterceptor(#NonNull Map<String, String> headers) {
this.headers = headers;
}
#NonNull
#Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
for (Map.Entry<String, String> header : headers.entrySet()) {
if (header.getKey() == null || header.getKey().trim().isEmpty()) {
continue;
}
if (header.getValue() == null || header.getValue().trim().isEmpty()) {
builder.removeHeader(header.getKey());
} else {
builder.header(header.getKey(), header.getValue());
}
}
return chain.proceed(builder.build());
}
}
Example of usage:
httpClientBuilder.networkInterceptors().add(new RequestHeadersNetworkInterceptor(new HashMap<String, String>()
{
{
put("User-Agent", getUserAgent());
put("Accept", "application/json");
}
}));
client = new OkHttpClient();
Request request = new Request.Builder().header("authorization", token).url(url).build();
MyWebSocketListener wsListener = new MyWebSocketListener(LudoRoomActivity.this);
client.newWebSocket(request, wsListener);
client.dispatcher().executorService().shutdown();
For those to whom okhttp3 interceptor still does not work. Consequence of adding interceptors is make sense! Kotlin example
My interceptor:
class MyOkHttpInterceptor : Interceptor, Logging {
#Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val mdc = MDC.getCopyOfContextMap()
var request = chain.request().newBuilder()
.header(CommonConstants.WS_USER_AGENT, CommonConstants.WS_USER_AGENT_SEARCH)
.header(CommonConstants.WS_HEADER_TRACED_ID, mdc[CommonConstants.WS_HEADER_TRACED_ID]!!)
.header(CommonConstants.WS_HEADER_ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.method(chain.request().method, chain.request().body)
.build()
return chain.proceed(request)
}
}
My logging interceptor:
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BASIC
I am adding header interceptor
I am adding logging interceptor
Do not use network interceptors!!!
val client = OkHttpClient.Builder()
.connectTimeout(httpConnectTimeOut, TimeUnit.SECONDS)
.writeTimeout(httpConnectTimeOut, TimeUnit.SECONDS)
.readTimeout(readTimeOut, TimeUnit.SECONDS)
.addInterceptor(MyOkHttpInterceptor())
.addInterceptor(interceptor)
.build()