Post multipart request with Android SDK
Update April 29th 2014:
My answer is kind of old by now and I guess you rather want to use some kind of high level library such as Retrofit.
Based on this blog I came up with the following solution:
http://blog.tacticalnuclearstrike.com/2010/01/using-multipartentity-in-android-applications/
You will have to download additional libraries to get MultipartEntity
running!
1) Download httpcomponents-client-4.1.zip from http://james.apache.org/download.cgi#Apache_Mime4J and add apache-mime4j-0.6.1.jar to your project.
2) Download httpcomponents-client-4.1-bin.zip from http://hc.apache.org/downloads.cgi and add httpclient-4.1.jar, httpcore-4.1.jar and httpmime-4.1.jar to your project.
3) Use the example code below.
private DefaultHttpClient mHttpClient;
public ServerCommunication() {
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
mHttpClient = new DefaultHttpClient(params);
}
public void uploadUserPhoto(File image) {
try {
HttpPost httppost = new HttpPost("some url");
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("Title", new StringBody("Title"));
multipartEntity.addPart("Nick", new StringBody("Nick"));
multipartEntity.addPart("Email", new StringBody("Email"));
multipartEntity.addPart("Description", new StringBody(Settings.SHARE.TEXT));
multipartEntity.addPart("Image", new FileBody(image));
httppost.setEntity(multipartEntity);
mHttpClient.execute(httppost, new PhotoUploadResponseHandler());
} catch (Exception e) {
Log.e(ServerCommunication.class.getName(), e.getLocalizedMessage(), e);
}
}
private class PhotoUploadResponseHandler implements ResponseHandler<Object> {
@Override
public Object handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
HttpEntity r_entity = response.getEntity();
String responseString = EntityUtils.toString(r_entity);
Log.d("UPLOAD", responseString);
return null;
}
}
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();
}
});
How to send a “multipart/form-data” POST in Android with Volley
I might be wrong on this but I think you need to implement your own com.android.volley.toolbox.HttpStack
for this because the default ones (HurlStack
if version > Gingerbread or HttpClientStack
) don't deal with multipart/form-data
.
Edit:
And indeed I was wrong. I was able to do it using MultipartEntity
in Request like this:
public class MultipartRequest extends Request<String> {
private MultipartEntity entity = new MultipartEntity();
private static final String FILE_PART_NAME = "file";
private static final String STRING_PART_NAME = "text";
private final Response.Listener<String> mListener;
private final File mFilePart;
private final String mStringPart;
public MultipartRequest(String url, Response.ErrorListener errorListener, Response.Listener<String> listener, File file, String stringPart)
{
super(Method.POST, url, errorListener);
mListener = listener;
mFilePart = file;
mStringPart = stringPart;
buildMultipartEntity();
}
private void buildMultipartEntity()
{
entity.addPart(FILE_PART_NAME, new FileBody(mFilePart));
try
{
entity.addPart(STRING_PART_NAME, new StringBody(mStringPart));
}
catch (UnsupportedEncodingException e)
{
VolleyLog.e("UnsupportedEncodingException");
}
}
@Override
public String getBodyContentType()
{
return entity.getContentType().getValue();
}
@Override
public byte[] getBody() throws AuthFailureError
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try
{
entity.writeTo(bos);
}
catch (IOException e)
{
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response)
{
return Response.success("Uploaded", getCacheEntry());
}
@Override
protected void deliverResponse(String response)
{
mListener.onResponse(response);
}
}
It's pretty raw but I tried it with an image and a simple string and it works. The response is a placeholder, doesn't make much sense to return a Response String in this case. I had problems using apache httpmime to use MultipartEntity so I used this https://code.google.com/p/httpclientandroidlib/ don't know if there's a better way.
Hope it helps.
Edit
You can use httpmime without using httpclientandroidlib, the only dependency is httpcore.
How to post a multi part form data from android to web api?
There are many post about multipart on stackoverflow,try this
public static String uploadMultipartFile(String root, String token,
String username, String sourceFileUri,
String fileStyle)
{
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
String pathToOurFile = sourceFileUri;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
StringBuffer response = new StringBuffer();
try
{
FileInputStream fileInputStream = new FileInputStream(new File(pathToOurFile));
URL url = new URL(root);
connection = (HttpURLConnection) url.openConnection();
if (token != null)
{
connection.setRequestProperty("Authorization", "Basic " + token);
}
if (username != null)
{
connection.setRequestProperty("Username", username);
}
if (fileStyle != null)
{
connection.setRequestProperty("file-type", fileStyle);
}
String fileExtension = FilenameUtils.getExtension(sourceFileUri);
String mime = Utils.getFileMIME(fileExtension);
Log.d("uploadMultipartFile","fileExtension:"+fileExtension+",mime:"+mime);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Cache-Control", "no-cache");
connection.setRequestProperty("User-Agent", "CodeJava Agent");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
+ pathToOurFile + "\"" + lineEnd);
outputStream.writeBytes("Content-Type: "+ mime + lineEnd);
outputStream.writeBytes(lineEnd);
byte[]bytes = IOUtils.toByteArray(fileInputStream);
outputStream.write(bytes);
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
int serverResponseCode = connection.getResponseCode();
String serverResponseMessage = connection.getResponseMessage();
Log.i(HttpUtil.class.getSimpleName(), String.valueOf(serverResponseCode));
Log.i(HttpUtil.class.getSimpleName(), serverResponseMessage);
fileInputStream.close();
outputStream.flush();
outputStream.close();
BufferedReader br=null;
if(connection.getResponseCode()>=200 && connection.getResponseCode()<300)
{
br = new BufferedReader(new InputStreamReader((connection.getInputStream())));
}
else if(connection.getResponseCode()>=400)
{
br = new BufferedReader(new InputStreamReader((connection.getErrorStream())));
}
String inputLine;
while ((inputLine = br.readLine()) != null) {
response.append(inputLine);
}
System.out.println("result from server:"+response.toString());
}
catch (Exception ex)
{
ex.printStackTrace();
}
return response.toString();
}
How to send a multipart request in Android with Volley
As commented, I cannot find where did you process the headers inside MultipartRequest class
So update your class like this:
public class MultipartRequest extends Request<String>{
...
private final Map<String, String> mHeaders;
...
public MultipartRequest(..., Map<String, String> headers, ...) {
super(...);
...
this.mHeaders = headers;
...
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return (mHeaders != null) ? mHeaders : super.getHeaders();
}
...
}
Related Topics
"Conversion to Dalvik Format Failed With Error 1" on External Jar
Developing For Android in Eclipse: R.Java Not Regenerating
Android Kotlin: Getting a Filenotfoundexception With Filename Chosen from File Picker
How to Pass Values Between Fragments
Jdbc VS Web Service For Android
How Exactly Does the Android:Onclick Xml Attribute Differ from Setonclicklistener
How to Use External Jars in an Android Project
How to Get Ip Address of the Device from Code
Why Does an Image Captured Using Camera Intent Gets Rotated on Some Devices on Android
How to Enable Multidexing With the New Android Multidex Support Library
How to Use Putextra() and Getextra() For String Data
How to Implement Onbackpressed() in Fragments
How to Open a Url in Android'S Web Browser from My Application
How to Get the Android Device'S Primary E-Mail Address
Sha-1 Fingerprint of Keystore Certificate
How to Avoid Reverse Engineering of an Apk File