Read edit at bottom of the question for possible alternative solution until the solution is found.
This is a successful post file with two parameters using POSTMan. I am trying to do the same with retrofit but receive BadRequest.
PostMan Settings:
Now here is how I am doing this in Android but failing:
Retrofit Service Interface:
@Multipart
@POST("jobDocuments/upload")
Call<ResponseBody> upload(@Part("file") MultipartBody.Part file,@Part("folder") MultipartBody.Part folder,@Part("name") MultipartBody.Part name);
This is my @Background method to run the network request with above service generated
CustDataClient service =
ServiceGenerator.createService(CustDataClient.class);
File file = new File(fileUri.getPath());
// create RequestBody instance from file
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part fileData =
MultipartBody.Part.createFormData("file", fileName, requestFile);
MultipartBody.Part folder =
MultipartBody.Part.createFormData("folder", "LeadDocuments");
MultipartBody.Part name =
MultipartBody.Part.createFormData("name", fileName);
// finally, execute the request
Call<ResponseBody> call = service.upload(fileData,folder,name);
try {
Response<ResponseBody> rr = call.execute();
ResponseBody empJobDocsResult = rr.body();//Bad Request here :(
Log.v("Upload", "success");
} catch (Exception ex) {
Log.e("Upload error:", ex.getMessage());
}
Here is my Web Api Method:
[Route("upload")]
[HttpPost]
public IHttpActionResult Upload()
{
if (HttpContext.Current.Request.Files.AllKeys.Any())
{
// Get the uploaded image from the Files collection
var httpPostedFile = HttpContext.Current.Request.Files["file"];
if (httpPostedFile != null)
{
// Validate the uploaded image(optional)
var folder = HttpContext.Current.Request.Form["folder"];
var fileName = HttpContext.Current.Request.Form["name"];
fileName = string.IsNullOrEmpty(fileName) ? httpPostedFile.FileName : fileName;
// Get the complete file path
var fileSavePath = Path.Combine(HttpContext.Current.Server.MapPath("~/Files/" + folder), fileName);
// Save the uploaded file to "UploadedFiles" folder
httpPostedFile.SaveAs(fileSavePath);
return Ok(new OkMessage { Message = "File uploaded successfully", Path = "/Files/" + folder + "/" + fileName });
}
}
return BadRequest("File not uploaded");
}
Please help where I am wrong and how to achieve this, is there any easy alternative to retrofit?
[Edit] This code is working successfully, Thanks to koush/ion:
Ion.with(getContext())
.load("POST", "http://www.dgheating.com/api/jobDocuments/upload")
.setMultipartParameter("folder", "LeadDocuments")
.setMultipartParameter("name", fileName)
.setMultipartFile("file", new File(imagePath))
.asJsonObject()
.setCallback(...);
Interface for Retrofit (API)
Response Class (JsonResponse)
API call from application
Error in fields, because of any of these server issue
I faced similar issue here: Android with Retrofit2 OkHttp3 - Multipart POST Error
I got my problem solved after taking @TommySM suggestion. If is still unclear to you, I think this is the solution:
The important part is to use
MediaType.parse("text/plain")
forMediaType
of String parameter (I believe your case is: folder & name parameter), usingokhttp3.MultipartBody.FORM
is a mistake.See these screenshots for the comparison:
1) Problematic POST
2) Correct POST
So, hope it's no too late, and if so - it might help somebody else :) my 2 cents about this is after having the same problem a while back:
The service definition, using
@Part
only (modify field names according to what your server expects)And for the magic trick, I refer to both parts just as
RequestBody
, using theMediaType.parse()
to each one with it's own type, relying on the@Multipart
definition for the request itself, no need forform-data
stuff, the same works for multiple files, and multiple fields:(I use a listener to return the callback response to a different part of the app (e.g. a calling activity)).
This definitely sends the file/s and the text field, other problems would probably stem from the server side.
Hope this Helps!
It looks like your service definition is wrong. Try
and
in your @Background method. This all assumes you are using Retrofit2.
Using Retrofit 2, you need to use either OkHttp’s RequestBody or MultipartBody.Part classes and encapsulate your file into a request body. Let’s have a look at the interface definition for file uploads. Have you seen https://futurestud.io/blog/retrofit-2-how-to-upload-files-to-server