I am using Retrofit to upload files to a server. It works correctly sometimes, but occasionally (and quite often), it gives me response 400 (Bad request) to the same request. Is it a known issue or what could be the problem?
This is whole code for upload:
public static void uploadFile(String authString,
Uri fileUri,
Context context,
MVPCallback<ResponseBody> mvpCallback) {
FileUploadService service =
ServiceGenerator.createService(FileUploadService.class, authString);
String filePath = FacadeMedia.getPath(context, fileUri);
if (filePath != null) {
File uploadFile = new File(filePath);
RequestBody requestFile = RequestBody.create(
MediaType.parse(context.getContentResolver().getType(fileUri)),
uploadFile);
MultipartBody.Part body =
MultipartBody.Part.createFormData("file", uploadFile.getName(), requestFile);
String content_disposition = "file; filename=\"" + uploadFile.getName() + "\"";
Call<ResponseBody> call = service.upload(body, content_disposition);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
if(response.isSuccessful()){
mvpCallback.onSuccess(response.body());
}else {
mvpCallback.onError(new Throwable(response.errorBody().toString()));
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
mvpCallback.onError(t);
}
});
}
}
public interface FileUploadService {
#Multipart
#POST(HttpFactory.UPLOAD_FILE_URL)
Call<ResponseBody> upload(
#Part MultipartBody.Part file,
#Header("Content-Disposition") String content_disposition
);
}
public class ServiceGenerator {
private static Retrofit retrofit;
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder();
public static <S> S createService(Class<S> serviceClass, String authString) {
httpClient.addInterceptor(chain -> {
Request request = chain.request()
.newBuilder()
.addHeader("Authorization", " Basic "+authString).build();
return chain.proceed(request);
});
retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
}
EDIT:
This is the errorBody message:
E/Bad request:: <html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>cloudflare-nginx</center>
</body>
</html>
So I fixed this my reinitializing OkHttpClient every ew request. Probably it has some old data in it. If anyone can elaborate on this, would be great.
Related
I am using retrofit 2 multipart for high quality Image upload (around 12 MB image). It works fine if I uses a Mobile Phone. But when I use Tablet it does not work. Can anyone tell me, what am I doing wrong here?
Here is my code:
public interface ApiDataService {
#Multipart
#POST("API Path Here")
Call<UploadImageResponse> Upload(#Header(Constants.KEY_AUTHORIZATION) String authorization,
#Part MultipartBody.Part file,
#Part("userId") RequestBody userId);
}
public class RetrofitInstance {
private static Retrofit retrofit = null;
public static Retrofit getInstance(){
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(100, TimeUnit.SECONDS)
.readTimeout(100,TimeUnit.SECONDS).build();
if(retrofit == null){
retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
Then I am using following method to Upload Image on server:
public void callUploadImageApi(String token, String fileName, String userId){
ApiDataService apiDataService = RetrofitInstance.getInstance().create(ApiDataService.class);
token = "Bearer "+ token;
File path = Environment.getExternalStorageDirectory();
File dir = new File(path.getAbsolutePath() + "/MyApplication/"+ fileName);
// create RequestBody instance from file
RequestBody requestFile =
RequestBody.create(
MediaType.parse("image/*"),
dir
);
// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part body =
MultipartBody.Part.createFormData("picture", dir.getName(), requestFile);
// add another part within the multipart request
RequestBody userIdString =
RequestBody.create(
okhttp3.MultipartBody.FORM, userId);
Call<UploadImageResponse> call = apiDataService.Upload(token, body, userIdString);
call.enqueue(new Callback<UploadImageResponse>() {
#Override
public void onResponse(Call<UploadImageResponse> call, Response<UploadImageResponse> response) {
if (response.body() != null) {
//success code here
}
}
#Override
public void onFailure(Call<UploadImageResponse> call, Throwable t) {
//failure code here
}
});
}
Thanks in advance for helping me...
I have a back end that I am able to upload a file to it by the following request in Pyhton:
data = {
"prop_post": 35
}
headers = {
# "Content-Type": "application/json",
"Authorization": "JWT " + t1,
}
if img_path is not None:
with open(img_path, 'rb') as image:
file_data = {
'photo': image
}
r = requests.post(POSTS_ENDPOINT, data=data,files=file_data, headers=headers)
that is my development environment. Now in production I am going to use Android as client to upload image. I am using Okhttp3. Here is the code that I am using to upload an image:
final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/jpg");
String file2 = utils.getRealPathFromURI2(obj.getPhotos_uri()[0], context);
File file = new File(file2);
RequestBody req = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("prop-post", Integer.toString(id))
.addFormDataPart("photo", "IMG-20190705-WA0002.jpg",
// RequestBody.create(MEDIA_TYPE_PNG, file.getAbsolutePath())).build();
RequestBody.create(MEDIA_TYPE_PNG, file)).build();
Request request = new Request.Builder()
.url(root + "images/")
.addHeader("Authorization", header)
.post(req)
.build();
OkHttpClient client = new OkHttpClient();
Response response2 = client.newCall(request).execute();
This request doesn't go through with 400 (Bad request) response. My file absolute location in Android is : /storage/emulated/0/WhatsApp/Media/WhatsApp Images/IMG-20190705-WA0002.jpg
I appreciate if some one can tell me what I am doing wrong.
Thanks in advance
I ended up using retrofit:
added these dependencies in gradle:
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
then defined the following interface:
public interface ImageAPI {
#Multipart
#POST("images/")
Call<ResponseBody> createPost( #Part MultipartBody.Part file, #Part("prop_post") RequestBody requestBody);
}
then my post call looks like this:
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder
.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder newRequest = request.newBuilder().header("Authorization", "mytoken");
return chain.proceed(newRequest.build());
}
});
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(rootUrl)
.client(okHttpClientBuilder.build())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
ImageAPI imageAPI = retrofit.create(ImageAPI.class);
String image_path = imagepath;//sets when browsing image
File file = new File(image_path);
RequestBody fileReqBody = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part part = MultipartBody.Part.createFormData("photo", file.getName(), fileReqBody);
RequestBody id= RequestBody.create(MediaType.parse("text/plain"), "68");
Call<ResponseBody> call = imageAPI.createPost(part, id);
try {
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d("tag", "onResponse: " + response.message().toString());
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("tag", "onResponse: " + t.getMessage());
}
});
} catch (Exception e) {
Log.d("tag", "onCreate: " + e.getMessage());
}
I am new to android .
I want to upload image as form data using Retrofit Post method.
I am using com.squareup.retrofit2:retrofit:2.3.0
This is my request body.
**Make interface like this add "MultipartBody.Part" in request and set your image path as post method and you can upload image using retrofit use this networkclient class to create retrofit instance **
public class NetworkClient {
private static final String BASE_URL = "";
private static Retrofit retrofit;
public static Retrofit getRetrofitClient(Context context) {
if (retrofit == null) {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
public interface UploadAPIs {
#Multipart
#POST("/upload")
Call<ResponseBody> uploadImage(#Part MultipartBody.Part file, #Part("name") RequestBody requestBody);
}
private void uploadToServer(String filePath) {
Retrofit retrofit = NetworkClient.getRetrofitClient(this);
UploadAPIs uploadAPIs = retrofit.create(UploadAPIs.class);
//Create a file object using file path
File file = new File(filePath);
// Create a request body with file and image media type
RequestBody fileReqBody = RequestBody.create(MediaType.parse("image/*"), file);
// Create MultipartBody.Part using file request-body,file name and part name
MultipartBody.Part part = MultipartBody.Part.createFormData("upload", file.getName(), fileReqBody);
//Create request body with text description and text media type
RequestBody description = RequestBody.create(MediaType.parse("text/plain"), "image-type");
//
Call call = uploadAPIs.uploadImage(part, description);
call.enqueue(new Callback() {
#Override
public void onResponse(Call call, Response response) {
}
#Override
public void onFailure(Call call, Throwable t) {
}
});
}
Try this
#Multipart
#POST(Global.updateProfilePicture)
Call<YOUR_RESPONSE_MODEL> updatePicture(#Header("Authorization") String authorization, #PartMap Map<String, RequestBody> params);
And API call should be like this
public void updatePic(String senderID, String receiverID, String type, File photo) {
mProgressDialog.show();
final Map<String, RequestBody> map = new HashMap<>();
try {
RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), photo);
map.put("image\"; filename=\"" + photo.getName() + "\"", fileBody);
} catch (Exception e) {
e.printStackTrace();
}
map.put("sender_id", RequestBody.create(MediaType.parse("multipart/form-data"), senderID));
map.put("receiver_id", RequestBody.create(MediaType.parse("multipart/form-data"), receiverID));
map.put("type", RequestBody.create(MediaType.parse("multipart/form-data"), type));
Call<YOUR_RESPONSE_MODEL> call = mApiInterface.updatePicture(ACCESS_TOKEN, map);
call.enqueue(new Callback<YOUR_RESPONSE_MODEL>() {
#Override
public void onResponse(#NonNull Call<YOUR_RESPONSE_MODEL> call, #NonNull Response<YOUR_RESPONSE_MODEL> response) {
if (mContext != null) {
mProgressDialog.dismiss();
// Dismiss Dialog
}
}
#Override
public void onFailure(#NonNull Call<YOUR_RESPONSE_MODEL> call, #NonNull Throwable t) {
if (mContext != null) {
mProgressDialog.dismiss();
}
}
});
}
I got output by doing request as following
UploadAPI Interface
`
#Multipart
#Headers({"TOKEN:XXXX"})
#POST("/api/messages/image")Call<ImageResult>uploadImage(#Part("sender_id")RequestBody sender_id,#Part("receiver_id")RequestBody receiver_id,#Part("type")RequestBody type,#Part MultipartBody.Part image);`
And Following is Method Code, I tried
`
private void uploadToServer(String filePath)
{
Retrofit retrofit = NetworkClient.getRetrofitClient(this, sendImageMsgURL);
UploadAPIs uploadAPIs = retrofit.create(UploadAPIs.class);
File file = new File(filePath);
MultipartBody.Part requestImage = null;
RequestBody requestFile = RequestBody.create(MediaType.parse("mutlipart/form-
data"),file);
requestImage = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
RequestBody sender_id = RequestBody.create(MediaType.parse("multipart/form-data"),
currentID);
RequestBody receiver_id = RequestBody.create(MediaType.parse("multipart/form-data"),
otherID);
RequestBody type = RequestBody.create(MediaType.parse("multipart/form-data"), "image");
Call<ImageResult> call = uploadAPIs.uploadImage(sender_id, receiver_id, type,
requestImage);
call.enqueue(new Callback<ImageResult>()
{
private Call<ImageResult> call;
private Response<ImageResult> response;
#Override
public void onResponse(Call<ImageResult> call, Response<ImageResult> response)
{
this.call = call;
this.response = response;
}
#Override
public void onFailure(Call call, Throwable t) {
Log.d("Error--------- :", t.getMessage());
}
});
}`
I want my android users to be able to upload a profile image to the django rest api. I use retrofit to handle the upload:
UserService
#Multipart
#POST("users/upload-profile-image/")
Call<ResponseBody> uploadProfileImage(#Part MultipartBody.Part image,
#Part("name") RequestBody name);
UserRepository
RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("upload", file.getName(), reqFile);
RequestBody name = RequestBody.create(MediaType.parse("text/plain"), "upload");
Call<ResponseBody> req = userServiceApi.uploadProfileImage(body, name);
req.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(#NonNull Call<ResponseBody> call,
#NonNull Response<ResponseBody> response) {
// Do Something
if (response.isSuccessful()) {
Log.d(TAG, "Successfully uploaded image");
} else {
eventBus.post(new FailUploadProfileImageEvent());
}
}
#Override
public void onFailure(#NonNull Call<ResponseBody> call, #NonNull Throwable t) {
t.printStackTrace();
}
});
To instantiate the userServiceAPI
userServiceApi = ServiceGenerator.createService(UserService.class, token);
ServiceGenerator
// Actual digits replaced with X
private static final String BASE_API_URL = "http://XXX.XXX.X.XXX:8000/";
private static OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
private static Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(BASE_API_URL)
.addConverterFactory(GsonConverterFactory.create());
public static <S> S createService(Class<S> serviceClass, String token) {
if (token != null)
okHttpBuilder.authenticator(new TokenAuthenticator(token));
OkHttpClient client = okHttpBuilder.build();
builder.client(client);
Retrofit retrofit = builder.build();
return retrofit.create(serviceClass);
}
users/urls.py
url(r'^upload-profile-image/$', views.UserProfileUploadImageView.as_view(), name="upload_profile_image"),
When I run the android app, no request is made to the server, why?
I'm trying to upload a videofile from my app.
Here's what I've got so far:
public class Download extends Application {
public interface upload {
#Multipart
#POST("new")
Call<Response> send(#Part("myFile") RequestBody file);
}
public void uploadFile(File xfile) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.0.3")
.addConverterFactory(GsonConverterFactory.create())
.build();
RequestBody file = RequestBody.create(MediaType.parse("video/*"), xfile);
upload xUpload = retrofit.create(upload.class);
Call<Response> call = xUpload.send(file);
try {
Response result = call.execute().body();
}
catch (IOException e)
{
Log.d("TEST3", " didn't work ");
}
}
}
I get the following error retrofit2.Response' is not a valid response body type. Did you mean ResponseBody? for method upload.send any ideas
I've read up on the retrofit2 webpage and tried the main example they have for uploading a file but it didn't work for two reasons.
1. I couldn't find right ServiceGenerator
2. My file was found in the Gallery and I streamed its contents to a temporary file which I'm to upload, I can't access it directly from its URI... or can I with retrofit2?
i use to upload image from retrofit 2 like this,it worked correctly
File file = new File(image.getPath());
RequestBody mFile = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("gallery", file.getName(), mFile);
RequestBody filename = RequestBody.create(MediaType.parse("text/plain"), id);
final NetworkCall networkCall=new NetworkCall(this);
Call<ResponseBody> call = networkCall.getRetrofit(false).uploadImage( filename, fileToUpload);
call.clone().enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
here is my network call class:
public class NetworkCall {
Context context;
ProgressDialog progressDialog;
public NetworkCall(Context context){
this.context = context;
}
public IApi getRetrofit(boolean isShowLoading){
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.connectTimeout(0, TimeUnit.SECONDS).readTimeout(0,TimeUnit.SECONDS);
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("Content_type","application/json")
.header("Accept", "application/json")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
Gson gson = new GsonBuilder()
.setLenient()
.create();
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
if (isShowLoading&&context instanceof BaseActivity)
showLoading();
// prepare call in Retrofit 2.0
IApi api = retrofit.create(IApi.class);
// Call<BaseResponce> call = api.callService(json);
//asynchronous call
// call.enqueue(this);
return api;
}
private void showLoading(){
try {
((BaseActivity)context).runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Please wait...");
progressDialog.setCancelable(false);
progressDialog.show();
}
});
}catch (Exception e){
e.printStackTrace();
}
}
public void dismissLoading(){
try {
((BaseActivity)context).runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.cancel();
progressDialog.dismiss();
}
});
}catch (Exception e){
e.printStackTrace();
}
}
}
i use this in IApi class
#Multipart
#POST("events/file_upload.json")
Call <ResponseBody> uploadImage(#Part("event_id") RequestBody id,#Part MultipartBody.Part part);
hope it helps