I have like 4 days, trying to make a Multipart Request using Retrofit 1.8.0 in android with any success. My interface looks something like this
@Multipart
@
I had similar problem today to send file and some fields, here is my solution
My interface, TypedFile is a Retrofit class
@Multipart
@POST("/api/Media/add")
void addMedia(@Part("file") TypedFile photo,
@Part("type") String type,
@Part("name") String name,
@Part("description") String description,
Callback<com.yourcompany.pojo.Media> callback);
in Activity
profileImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent galleryIntent = new Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(galleryIntent , RESULT_GALLERY );
}
});
and then
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RESULT_GALLERY :
if (null != data) {
imageUri = data.getData();
String selectedImagePath = null;
Uri selectedImageUri = data.getData();
Cursor cursor = activity.getContentResolver().query(selectedImageUri, null, null,
null, null);
if (cursor == null) {
selectedImagePath = imageUri.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
selectedImagePath = cursor.getString(idx);
}
File file = new File(selectedImagePath);
waiter.setVisibility(View.VISIBLE);
_YOUR_APP_._YOUR_INTERFACE_.addMedia(new TypedFile("image/*", file), "avatar", "avatar", "avatar", new Callback<Media>() {
@Override
public void success(Media media, Response response) {
}
@Override
public void failure(RetrofitError error) {
}
});
}
break;
default:
break;
}
}
Media class is simple pojo to keep answer
public class Media {
@Expose
private int[] data;
/**
*
* @return
* The data
*/
public int getData() {
return data[0];
}
/**
*
* @param data
* The data
*/
public void setData(int[] data) {
this.data = data;
}
}
I did this instead for the interface
interface MultipartFormDataService {
@POST("/{uploadPath}")
void multipartFormDataSend(
@EncodedPath("uploadPath") String uploadPath,
@Body MultipartTypedOutput multipartTypedOutput,
Callback<String> cb);
}
Then later when I call it, it looks like this
// creating the Multipart body using retrofit
MultipartTypedOutput multipartTypedOutput = new MultipartTypedOutput();
TypedString idParam = new TypedString("[ID Value]")
TypedString bodyParam = new TypedString("[Body text]")
ByteArrayTypedOutput byteMultipartTypedOut = new ByteArrayTypedOutput(bytes)
// add parts
multipartTypedOutput.addPart("id", idParam);
multipartTypedOutput.addPart("body", bodyParam);
multipartTypedOutput.addPart("attachment", extraParamTypedString);
// send
multipartService.multipartFormDataSend(
"[TARGET URL]",
multipartTypedOutput,
aCallback);
My ByteArrayTypedOutput was simple
public class ByteArrayTypedOutput implements TypedOutput {
private MultipartFormMetadata metadata;
private byte[] imageData;
public ByteArrayTypedOutput(MultipartFormMetadata metadata, byte[] imageData)
this.metadata = metadata;
this.imageData = imageData;
}
@Override
public String fileName() {
return metadata.fileName;
}
@Override
public String mimeType() {
return metadata.fileMimeType;
}
@Override
public long length() {
return imageData.length;
}
@Override
public void writeTo(OutputStream outputStream) throws IOException {
outputStream.write(imageData);
}
}
If you see the examples on http://square.github.io/retrofit/ the object types for your "id" and "part[body]" parameters need to be TypedString and not String. TypedString sets the appropriate MIME type and does the conversion to bytes:
https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit/mime/TypedString.java