POST Multipart Form Data using Retrofit 2.0 including image
I am highlighting the solution in both 1.9 and 2.0 since it is useful for some
In 1.9
, I think the better solution is to save the file to disk and use it as Typed file like:
RetroFit 1.9
(I don't know about your server-side implementation) have an API interface method similar to this
@POST("/en/Api/Results/UploadFile")
void UploadFile(@Part("file") TypedFile file,
@Part("folder") String folder,
Callback<Response> callback);
And use it like
TypedFile file = new TypedFile("multipart/form-data",
new File(path));
For RetroFit 2 Use the following method
RetroFit 2.0 ( This was a workaround for an issue in RetroFit 2 which is fixed now, for the correct method refer jimmy0251's answer)
API Interface:
public interface ApiInterface {
@Multipart
@POST("/api/Accounts/editaccount")
Call<User> editUser(@Header("Authorization") String authorization,
@Part("file\"; filename=\"pp.png\" ") RequestBody file,
@Part("FirstName") RequestBody fname,
@Part("Id") RequestBody id);
}
Use it like:
File file = new File(imageUri.getPath());
RequestBody fbody = RequestBody.create(MediaType.parse("image/*"),
file);
RequestBody name = RequestBody.create(MediaType.parse("text/plain"),
firstNameField.getText()
.toString());
RequestBody id = RequestBody.create(MediaType.parse("text/plain"),
AZUtils.getUserId(this));
Call<User> call = client.editUser(AZUtils.getToken(this),
fbody,
name,
id);
call.enqueue(new Callback<User>() {
@Override
public void onResponse(retrofit.Response<User> response,
Retrofit retrofit) {
AZUtils.printObject(response.body());
}
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
});
Retrofit2 failed to upload image with Multipart or RequestBody
The issue were caused by inability to read the file from disk.
Adding android:requestLegacyExternalStorage="true"
to the Android Manifest worked for me with Android sdk 29.
<application
android:name=".MyApplication"
android:requestLegacyExternalStorage="true" ...
Apart from adding <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
permission.
Andrioid Retrofit Multipart Image Upload 500 error
I have fixed issue. I have posted both params in single request body and changed param as @Part to @Body.
fun uploadImage(filepath: String) {
Log.e("info", ">>>>>status>>>>>" + ">>>>>>" + filepath)
val file = File(filepath)
Log.d("file...", "length..." + file.length())
val mimeType = getMimeType(file)
val metaobject = JSONObject()
metaobject.put("eye", "OD")
val requestBody: RequestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("metadata", metaobject.toString())
.addFormDataPart(
"file", file.name,
file.asRequestBody(mimeType!!.toMediaTypeOrNull())
)
.build()
val header = HashMap<String, String>()
header["Authorization"] =
"Bearer <<token>>"
val request = ApiService.buildService(ApiHelper::class.java)
val call = request.sendMediaFile(header,requestBody)
call.enqueue(
object : Callback<ResponseBody?> {
override fun onResponse(
call: Call<ResponseBody?>,
response: Response<ResponseBody?>
) {
Log.e("Upload", "success" + response.body().toString())
Log.e("Upload", "success" + response.errorBody().toString())
}
override fun onFailure(call: Call<ResponseBody?>, t: Throwable) {
Log.e("Upload error:", t.message!!)
}
})
}
and in helper class
@POST("{profileId}/files")
fun sendMediaFile(
@Path("profileId") profile_id: String,
@HeaderMap headers: Map<String, String>,
@Body metadata: RequestBody?
): Call<ResponseBody?>
Android having problems while uploading Images using Retrofit multipart?
Add this
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
inside the manifest tag of your manifest file.Makes sure its outside the application tag however.
Retrofit @Part Multipartbody.Part with @multipart throws exception
@Part MultipartBody.Part file. It throws Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $.
This is GSON error and it means that model that you provided does not match to response you received from your server (In your case you received plane string instead of JSON)
In order to solve your issue please post full response from server so as your model class
Retrofit 2 Multipart image upload with data
We test api in Postman... So my Create Post Answer includes (all Dynamic)
- Headers
- Simple Strings
- Single Image
- Array Of Images
- Array Of Categories
- Array Of Features
Almost all things
Below is the Postman image for api testing...
- Headers Image
So for this ...
Below is my Api...
@POST("post-create")
Call<PostCreateResponse> getPostCreateBodyResponse(
@Header("Accept") String accept,
@Header("Authorization") String authorization,
@Body RequestBody file
);
Now Retrofit Client area--->
private Retrofit retrofit;
// This is Client
private RetrofitClient() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.connectTimeout(100, TimeUnit.SECONDS);
httpClient.readTimeout(100,TimeUnit.SECONDS);
httpClient.writeTimeout(100,TimeUnit.SECONDS);
httpClient.addInterceptor(logging); // <-- this is the important line!
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
}
This is the way I Made the Request...
/*
* -------------- Retrofit post Create single featured Image Working with MultipartBody -----------
* */
progressDialog.show();
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
builder.addFormDataPart("title", "3 room Current Free")
.addFormDataPart("location", "Dhaka")
.addFormDataPart("latitude", "23.7515")
.addFormDataPart("longitude", "90.3625")
.addFormDataPart("condition", "1")
.addFormDataPart("rent_amount", "123456")
.addFormDataPart("is_negotiable", "0")
.addFormDataPart("available_from", "2018-10-15");
// Categories
for (int categoryId : categories) {
builder.addFormDataPart("categories[]", String.valueOf(categoryId));
}
// Features
for (Integer featureId : features) {
builder.addFormDataPart("features[]", String.valueOf(featureId));
}
// featured Image
if (photoPaths.get(0) != null) {
File featured_image = new File(photoPaths.get(0));
if (featured_image.exists()) {
// If you want to use Bitmap then use this
Bitmap bmp = BitmapFactory.decodeFile(featured_image.getAbsolutePath());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 30, bos);
builder.addFormDataPart("featured_photo", featured_image.getName(), RequestBody.create(MultipartBody.FORM, bos.toByteArray()));
// If you want to use direct file then use this ( comment out the below part and comment the above part )
//builder.addFormDataPart("featured_photo", featured_image.getName(), RequestBody.create(MultipartBody.FORM, featured_image));
}
}
// Images
for (String photoPath : photoPaths) {
if (photoPath != null) {
File images = new File(photoPath);
if (images.exists()) {
builder.addFormDataPart("images[]", images.getName(), RequestBody.create(MultipartBody.FORM, images));
}
}
}
RequestBody requestBody = builder.build();
Call<PostCreateResponse> call = RetrofitClient.getInstance().getApi().getPostCreateBodyResponse(Accept, Authorization, requestBody);
call.enqueue(new Callback<PostCreateResponse>() {
@Override
public void onResponse(Call<PostCreateResponse> call, Response<PostCreateResponse> response) {
progressDialog.dismiss();
Log.d(TAG, "onResponse: response code: retrofit: " + response.code());
}
@Override
public void onFailure(Call<PostCreateResponse> call, Throwable t) {
}
});
/*
* ---------------- Retrofit post Create single featured Image Working with MultipartBody----------------
* */
I hope this will help you all... thanks
Multipart request with retrofit 2.0 Android Taking too much time to request
You can increase the timeouts in the Retrofit settings.
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://10.0.2.2:3000/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create());
Maybe it help for you!
More: https://futurestud.io/tutorials/retrofit-2-customize-network-timeouts
Related Topics
How to Set Up Android Studio to Work Completely Offline
Android Force Gpu Rendering How to Enable and Disable
How to Check If a Value Exists Already in a Firebase Data Class Android
Photo Rotated from Camera (Samsung Device)
How to Set Android_Ndk_Home So That Android Studio Does Not Ask for Ndk Location
How to Remove Focus from Edittext When User Is Done Editing
How to Access the Camera from Within a Webview
Alarm Manager Won't Work When the App Is Killed in the Background and Device Is Locked
How to Remove the Black Bar Appearing At the Bottom
How to Edit Files Inside the Android Adb Shell
How to Create an Android View Pager With a Dots Indicator
Setting Onclicklistener for the Drawable Right of an Edittext
Flutter Keyboard Makes Textfield Hide
How to Set the Preview Image in Videoview Before Playing
Not Opening Specific Activity on Notification Click When the App Is in Background/Not Running
How to Manage Startactivityforresult on Android
How to Get the Result of Onpostexecute() to Main Activity Because Asynctask Is a Separate Class
Android Sqlite: How to Retrieve Specific Data from Particular Column