When posting a new product, my server needs to catch files with keys. There's no limit to how many files. Files are unlimited.
With Retrofit 1.9, everything worked perfect. After I update to Retrofit 2, my server does not receive any file.
If I edit the server, it won't be backward compatible anymore. I need to make the android app works like it worked with Retrofit 1.9.
Here's how I implemented.
class to create ApiService interface.
public class ApiClient {
public interface ApiInterface {
@Multipart
@POST("/products/")
void uploadProduct(
@PartMap Map<String, String> params,
@PartMap Map<String, TypedFile> files,
Callback<Product> cb);
}
}
using the ApiService.
Map<String, String> params = new HashMap<>();
params.put("title", title);
params.put("price", price);
params.put("content", content);
Map<String, TypedFile> files = new HashMap<>();
for (int pos = 0; pos < photoPaths.length; pos++) {
if (!Strings.isNullOrEmpty(photoPaths[pos])) {
TypedFile typedFile = new TypedFile("multipart/form-data", new File(photoPaths[pos]));
files.put("photo_" + String.valueOf(pos + 1), typedFile);
}
}
apiInterface.uploadProduct(params, files, cb);
class to create ApiService interface.
public class ApiClient {
public interface ApiInterface {
@Multipart
@POST("/products/")
Call<Product> uploadProduct(
@PartMap Map<String, RequestBody> params,
@PartMap Map<String, RequestBody> files);
}
public static final String MULTIPART_FORM_DATA = "multipart/form-data";
public static RequestBody createRequestBody(@NonNull File file) {
return RequestBody.create(
MediaType.parse(MULTIPART_FORM_DATA), file);
}
public static RequestBody createRequestBody(@NonNull String s) {
return RequestBody.create(
MediaType.parse(MULTIPART_FORM_DATA), s);
}
}
using the ApiService
Map<String, RequestBody> params = new HashMap<>();
params.put("title", ApiClient.createRequestBody(title));
params.put("price", ApiClient.createRequestBody(price));
params.put("content", ApiClient.createRequestBody(content));
Map<String, RequestBody> files = new HashMap<>();
for (int pos = 0; pos < photoPaths.length; pos++) {
if (!TextUtils.isEmpty(photoPaths[pos])) {
RequestBody requestBody = ApiClient.createRequestBody(new File(photoPaths[pos]));
files.put("photo_" + String.valueOf(pos + 1), requestBody);
}
}
Call<Product> call = apiInterface.uploadProduct(params, files);
You can send a POST / PUT request by either submitting a body depending on the API Content Type Form Data, Form URL Encoded, or using JSON. To submit a JSON object you can use the @SerializedName to specify how to send each field data in the request.
Multipart upload allows you to upload a single object as a set of parts. Each part is a contiguous portion of the object's data. You can upload these object parts independently and in any order. If transmission of any part fails, you can retransmit that part without affecting other parts.
I applied this solution and it's now fixed.
Here's how I implemented.
Map<String, RequestBody> params = new HashMap<>();
params.put("title", ApiClient.createRequestBody(title));
params.put("price", ApiClient.createRequestBody(price));
params.put("content", ApiClient.createRequestBody(content));
Map<String, RequestBody> files = new HashMap<>();
for (int pos = 0; pos < photoPaths.length; pos++) {
if (!TextUtils.isEmpty(photoPaths[pos])) {
RequestBody requestBody = ApiClient.createRequestBody(new File(photoPaths[pos]));
// fix is right here
String key = String.format("%1$s\"; filename=\"%1$s", "photo_" + String.valueOf(pos + 1));
files.put(key, requestBody);
}
}
Call<Product> call = apiInterface.uploadProduct(params, files);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With