82

I'm trying to do something I thought would be relatively simple: Upload an image to a server with the Android SDK. I'm found a lot of example code:

http://groups.google.com/group/android-developers/browse_thread/thread/f9e17bbaf50c5fc/46145fcacd450e48

http://linklens.blogspot.com/2009/06/android-multipart-upload.html

But neither work for me. The confusion I keep running into is what is really needed to make a multipart request. What is the simplest way to have a multipart upload (with an image) for Android?

Any help or advice would be greatly appreciated!

Harshad Pansuriya
  • 20,189
  • 8
  • 67
  • 95
jpoz
  • 2,257
  • 1
  • 23
  • 29
  • What are the problems you're having with the methods you've tried so far? – Christopher Orr Jan 07 '10 at 01:37
  • 1
    Oh lots of problems. Currently getting the photo uri passed back from the photo picker into a file I can attach to a MultipartEntity. But I'm not even sure this is the correct way to construct a multiport request. – jpoz Jan 07 '10 at 18:36
  • This is *really* old. Someone needs to answer this with modern libraries, or at least post code that works! So many things have been deprecated in the decade since this question was asked, I'm having a hard time finding something that even compiles. – SMBiggs Aug 01 '21 at 02:55

12 Answers12

104

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;
    }

}
vinzenzweber
  • 3,379
  • 4
  • 24
  • 26
  • 4
    I can't find the MultipartEntity as well as HttpMultipartClient library in Android. Could you help me please? – Nguyen Minh Binh Apr 09 '11 at 14:40
  • 23
    this is the correct answer. it's a shame that this class isn't included in the Android SDK. – moonlightcheese Mar 05 '12 at 17:52
  • 2
    Why do you need apache-mime4j-0.6.1.jar? – JPM Jun 06 '12 at 19:20
  • 1
    Works perfectly - I only needed to add the httpmime-4.1.jar (apparently httpmime-4.2.jar) – domsom Oct 24 '12 at 08:53
  • how big is this library? I don't want to commit to using a full library for 1 class – jiduvah Jan 28 '13 at 17:15
  • It worked like a charm. For those who didn't get expected result: if back-end developers tells you to upload photo under name "uploadFileName" please ask for server-side code snippet or html form to verify. I was struggling 3 hours and file was not uploaded, and finally backend guys showed me code and I found out that I just should use another property name... – Artem Svystun Jun 07 '13 at 19:51
  • Works like a charm, except now the ADT debugger is throwing ClassNotFoundException. I'm assuming I need to tell it to send the additional jars to the phone I'm debugging on (some old HTC), any idea on how to do that? – Jorn Jun 26 '13 at 21:11
  • This really helped me a lot; I replaced a LOT of manual InputStream/OutputStream code, as well as HTTPS handling, by using these classes instead. 40 execution lines (excluding adding parameters) down to 2, plus a reusable multithreaded ResponseHandler! – James Perih Sep 10 '13 at 05:11
  • 5
    anyone looking for this now first set of files are now here : http://psg.mtu.edu/pub/apache//james/mime4j/ – Keeano Oct 02 '13 at 22:04
  • 5
    Thanks for the solution. However, `MultipartEntity`is deprecated now. This post may guide those looking to use `MultipartEntityBuilder` instead: http://stackoverflow.com/a/19188010/1276636 – Sufian Nov 05 '13 at 09:26
  • There are a lot of answers out there that claim to be correct but this one is def it. Ty Ty – KBusc Jan 13 '14 at 15:44
  • Are you sure httpClient jar needs to be added? – Muhammad Babar Apr 01 '14 at 13:17
  • I'm not sure if there isn't a more elegant solution to this issue yet!? My answer now dates back 3 years already. – vinzenzweber Apr 01 '14 at 15:36
  • 1
    use compile 'org.apache.httpcomponents:httpmime:4.3.4' compile 'org.apache.httpcomponents:httpcore:4.3.2' for android studio dependencies – Tyler Davis Aug 07 '14 at 18:38
  • @vinzenzweber can I get some sample code of retrofit for post, get, multipart upload file with progress? – Usman Afzal Oct 28 '14 at 11:28
  • sorry, but I don't have any sample code for retrofit – vinzenzweber Oct 28 '14 at 17:33
  • Many people has suggested that it is deprecated now.Then how can I post any File to server using Multipart. – Rahul Kushwaha Jan 11 '19 at 10:44
48

As MultiPartEntity is deprecated. So here is the new way to do it! And you only need httpcore.jar(latest) and httpmime.jar(latest) download them from Apache site.

try
{
    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost(URL);

    MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
    entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);

    entityBuilder.addTextBody(USER_ID, userId);
    entityBuilder.addTextBody(NAME, name);
    entityBuilder.addTextBody(TYPE, type);
    entityBuilder.addTextBody(COMMENT, comment);
    entityBuilder.addTextBody(LATITUDE, String.valueOf(User.Latitude));
    entityBuilder.addTextBody(LONGITUDE, String.valueOf(User.Longitude));

    if(file != null)
    {
        entityBuilder.addBinaryBody(IMAGE, file);
    }

    HttpEntity entity = entityBuilder.build();
    post.setEntity(entity);
    HttpResponse response = client.execute(post);
    HttpEntity httpEntity = response.getEntity();
    result = EntityUtils.toString(httpEntity);
    Log.v("result", result);
}
catch(Exception e)
{
    e.printStackTrace();
}
JJD
  • 50,076
  • 60
  • 203
  • 339
Muhammad Babar
  • 8,084
  • 5
  • 39
  • 56
16

Here is the LIGHT WEIGHTED solution which worked for me with no external HTTPCore and such libs. I was facing issue of 64K methods so have no option left to avoid HTTPCore libraries

import java.util.List;

import java.io.BufferedReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

/**
 * This utility class provides an abstraction layer for sending multipart HTTP
 * POST requests to a web server.
 *
 * @author www.codejava.net
 */
public class MultipartUtility {
    private final String boundary;
    private static final String LINE_FEED = "\r\n";
    private HttpURLConnection httpConn;
    private String charset;
    private OutputStream outputStream;
    private PrintWriter writer;

    /**
     * This constructor initializes a new HTTP POST request with content type
     * is set to multipart/form-data
     *
     * @param requestURL
     * @param charset
     * @throws IOException
     */
    public MultipartUtility(String requestURL, String charset)
            throws IOException {
        this.charset = charset;

        // creates a unique boundary based on time stamp
        boundary = "===" + System.currentTimeMillis() + "===";

        URL url = new URL(requestURL);
        httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setUseCaches(false);
        httpConn.setDoOutput(true); // indicates POST method
        httpConn.setDoInput(true);
        httpConn.setRequestProperty("Content-Type",
                "multipart/form-data; boundary=" + boundary);
        httpConn.setRequestProperty("User-Agent", "CodeJava Agent");
        httpConn.setRequestProperty("Test", "Bonjour");
        outputStream = httpConn.getOutputStream();
        writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
                true);
    }

    /**
     * Adds a form field to the request
     *
     * @param name  field name
     * @param value field value
     */
    public void addFormField(String name, String value) {
        writer.append("--" + boundary).append(LINE_FEED);
        writer.append("Content-Disposition: form-data; name=\"" + name + "\"")
                .append(LINE_FEED);
        writer.append("Content-Type: text/plain; charset=" + charset).append(
                LINE_FEED);
        writer.append(LINE_FEED);
        writer.append(value).append(LINE_FEED);
        writer.flush();
    }

    /**
     * Adds a upload file section to the request
     *
     * @param fieldName  name attribute in <input type="file" name="..." />
     * @param uploadFile a File to be uploaded
     * @throws IOException
     */
    public void addFilePart(String fieldName, File uploadFile)
            throws IOException {
        String fileName = uploadFile.getName();
        writer.append("--" + boundary).append(LINE_FEED);
        writer.append(
                "Content-Disposition: form-data; name=\"" + fieldName
                        + "\"; filename=\"" + fileName + "\"")
                .append(LINE_FEED);
        writer.append(
                "Content-Type: "
                        + URLConnection.guessContentTypeFromName(fileName))
                .append(LINE_FEED);
        writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
        writer.append(LINE_FEED);
        writer.flush();

        FileInputStream inputStream = new FileInputStream(uploadFile);
        byte[] buffer = new byte[4096];
        int bytesRead = -1;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        outputStream.flush();
        inputStream.close();

        writer.append(LINE_FEED);
        writer.flush();
    }

    /**
     * Adds a header field to the request.
     *
     * @param name  - name of the header field
     * @param value - value of the header field
     */
    public void addHeaderField(String name, String value) {
        writer.append(name + ": " + value).append(LINE_FEED);
        writer.flush();
    }

    /**
     * Completes the request and receives response from the server.
     *
     * @return a list of Strings as response in case the server returned
     * status OK, otherwise an exception is thrown.
     * @throws IOException
     */
    public List<String> finish() throws IOException {
        List<String> response = new ArrayList<String>();

        writer.append(LINE_FEED).flush();
        writer.append("--" + boundary + "--").append(LINE_FEED);
        writer.close();

        // checks server's status code first
        int status = httpConn.getResponseCode();
        if (status == HttpURLConnection.HTTP_OK) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    httpConn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                response.add(line);
            }
            reader.close();
            httpConn.disconnect();
        } else {
            throw new IOException("Server returned non-OK status: " + status);
        }

        return response;
    }
}

USAGE

private void uploadMedia() {
        try {

            String charset = "UTF-8";
            File uploadFile1 = new File("/sdcard/myvideo.mp4");
            String requestURL = Data.BASE_URL+Data.URL_UPLOAD_REACTION_TEST;

            MultipartUtility multipart = new MultipartUtility(requestURL, charset);

//            multipart.addHeaderField("User-Agent", "CodeJava");
//            multipart.addHeaderField("Test-Header", "Header-Value");

            multipart.addFormField("friend_id", "Cool Pictures");
            multipart.addFormField("userid", "Java,upload,Spring");

            multipart.addFilePart("uploadedfile", uploadFile1);

            List<String> response = multipart.finish();

            Log.v("rht", "SERVER REPLIED:");

            for (String line : response) {
                Log.v("rht", "Line : "+line);

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

PHP Code to accept upload

<?php

    $friend_id = $_REQUEST['friend_id'];
    $userid = $_REQUEST['userid'];

    echo 'friend_id : '.$friend_id. ' userid '.$userid;

    move_uploaded_file($_FILES['uploadedfile']['tmp_name'], "./uploads/".$_FILES["uploadedfile"]["name"]);

?>
Rohit Mandiwal
  • 10,258
  • 5
  • 70
  • 83
  • For this boundary my code threw 400 Bad Request boundary = "===" + System.currentTimeMillis() + "==="; Then I changed the boundary as boundary = "---" + System.currentTimeMillis(); Then the request was properly parsed at back-end. – Prashant Jun 08 '17 at 14:35
  • why is this so complicated...? No exactly a question. Just annoying that it takes so much to do this in this environment. – Neo42 Feb 05 '18 at 21:36
  • I used this with success, but had to remove the last append(LINEFEED) in addFilePart(). Thanks. – David Wood Sep 17 '18 at 13:54
6

More easy, light (32k), and many more performance:

Android Asynchronous Http Client library: http://loopj.com/android-async-http/

Implementation:

How to send a “multipart/form-data” POST in Android with Volley

Community
  • 1
  • 1
Hpsaturn
  • 2,702
  • 31
  • 38
3

I highly recommend Loopj.

I have successfully used it to upload multiple files at once, including different mime types. Simply do this:

File myVideo = new File("/path/to/myvideo.mp4");
File myPic = new File("/path/to/mypic.jpg");
RequestParams params = new RequestParams();
try {
  params.put("profile_picture", myPic);
  params.put("my_video", myVideo);
} catch(FileNotFoundException e) {}

For large or many files you might have to increase the timeout amount else the default timeout is used which might be too short:

client.setTimeout(500000) //make this the appropriate timeout in milliseconds

Please see this links for a full description of loopj and how to use it, by far the easiest async http library I have come across:

http://loopj.com/android-async-http/ http://loopj.com/android-async-http/doc/com/loopj/android/http/AsyncHttpClient.html

Chris
  • 4,593
  • 1
  • 33
  • 37
3

Try this:

    public void SendMultipartFile() {
    Log.d(TAG, "UPLOAD: SendMultipartFile");
    DefaultHttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost( <url> );

    File file = new File("/sdcard/spider.jpg");

    Log.d(TAG, "UPLOAD: setting up multipart entity");

    MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
    Log.d(TAG, "UPLOAD: file length = " + file.length());
    Log.d(TAG, "UPLOAD: file exist = " + file.exists());

    try {
        mpEntity.addPart("datafile", new FileBody(file, "application/octet"));
        mpEntity.addPart("id", new StringBody("1"));
    } catch (UnsupportedEncodingException e1) {
        Log.d(TAG, "UPLOAD: UnsupportedEncodingException");
        e1.printStackTrace();
    }

    httppost.setEntity(mpEntity);
    Log.d(TAG, "UPLOAD: executing request: " + httppost.getRequestLine());
    Log.d(TAG, "UPLOAD: request: " + httppost.getEntity().getContentType().toString());


    HttpResponse response;
    try {
        Log.d(TAG, "UPLOAD: about to execute");
        response = httpclient.execute(httppost);
        Log.d(TAG, "UPLOAD: executed");
        HttpEntity resEntity = response.getEntity();
        Log.d(TAG, "UPLOAD: respose code: " + response.getStatusLine().toString());
        if (resEntity != null) {
            Log.d(TAG, "UPLOAD: " + EntityUtils.toString(resEntity));
        }
        if (resEntity != null) {
            resEntity.consumeContent();
        }
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Jóni
  • 364
  • 1
  • 3
  • 16
2
public class Multipart{
    private final Map<String, String> headrs;
    private String url;
    private HttpURLConnection con;
    private OutputStream os;

    private String delimiter = "--";
    private String boundary = "TRR" + Long.toString(System.currentTimeMillis()) + "TRR";

    public Multipart (String url, Map<String, String> headers) {
        this.url = url;
        this.headrs = headers;
    }

    public void connectForMultipart() throws Exception {
        con = (HttpURLConnection) (new URL(url)).openConnection();
        con.setRequestMethod("POST");
        con.setDoInput(true);
        con.setDoOutput(true);
        con.setRequestProperty("Connection", "Keep-Alive");
        for (Map.Entry<String, String> entry : headrs.entrySet()) {
            con.setRequestProperty(entry.getKey(), entry.getValue());
        }
        con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
        con.connect();
        os = con.getOutputStream();
    }

    public void addFormPart(String paramName, String value) throws Exception {
        writeParamData(paramName, value);
    }

    public void addFilePart(String paramName, String fileName, byte[] data) throws Exception {
        os.write((delimiter + boundary + "\r\n").getBytes());
        os.write(("Content-Disposition: form-data; name=\"" + paramName + "\"; filename=\"" + fileName + "\"\r\n").getBytes());
        os.write(("Content-Type: application/octet-stream\r\n").getBytes());
        os.write(("Content-Transfer-Encoding: binary\r\n").getBytes());
        os.write("\r\n".getBytes());

        os.write(data);

        os.write("\r\n".getBytes());
    }

    public void finishMultipart() throws Exception {
        os.write((delimiter + boundary + delimiter + "\r\n").getBytes());
    }


    public String getResponse() throws Exception {
        InputStream is = con.getInputStream();
        byte[] b1 = new byte[1024];
        StringBuffer buffer = new StringBuffer();

        while (is.read(b1) != -1)
            buffer.append(new String(b1));

        con.disconnect();

        return buffer.toString();
    }


    private void writeParamData(String paramName, String value) throws Exception {


        os.write((delimiter + boundary + "\r\n").getBytes());
        os.write("Content-Type: text/plain\r\n".getBytes());//;charset=utf-8
        os.write(("Content-Disposition: form-data; name=\"" + paramName + "\"\r\n").getBytes());
        ;
        os.write(("\r\n" + value + "\r\n").getBytes());


    }
}

Then call below

Multipart multipart = new Multipart(url__, map);
            multipart .connectForMultipart();
multipart .addFormPart(entry.getKey(), entry.getValue());
multipart .addFilePart(KeyName, "FileName", imagedata);
multipart .finishMultipart();
VV W
  • 169
  • 7
2

You can you use GentleRequest, which is lightweight library for making http requests(DISCLAIMER: I am the author):

Connections connections = new HttpConnections();
Binary binary = new PacketsBinary(new 
BufferedInputStream(new FileInputStream(file)), 
   file.length());
//Content-Type is set to multipart/form-data; boundary= 
//{generated by multipart object}
MultipartForm multipart = new HttpMultipartForm(
    new HttpFormPart("user", "aplication/json", 
       new JSONObject().toString().getBytes()),
    new HttpFormPart("java", "java.png", "image/png", 
       binary.content()));
Response response = connections.response(new 
    PostRequest(url, multipart));
if (response.hasSuccessCode()) {
    byte[] raw = response.body().value();
    String string = response.body().stringValue();
    JSONOBject json = response.body().jsonValue();
 } else {

 }

Feel free to check it out: https://github.com/Iprogrammerr/Gentle-Request

Binary Igor
  • 168
  • 1
  • 5
1

Remove all your httpclient, httpmime dependency and add this dependency compile 'commons-httpclient:commons-httpclient:3.1'. This dependency has built in MultipartRequestEntity so that you can easily upload one or more files to the server

public class FileUploadUrlConnection extends AsyncTask<String, String, String> {
private Context context;
private String url;
private List<File> files;

public FileUploadUrlConnection(Context context, String url, List<File> files) {
    this.context = context;
    this.url = url;
    this.files = files;
}

@Override
protected String doInBackground(String... params) {

    HttpClient client = new HttpClient();
    PostMethod post = new PostMethod(url);
    HttpClientParams connectionParams = new HttpClientParams();

    post.setRequestHeader(// Your header goes here );

    try {
        Part[] parts = new Part[files.size()];
        for (int i=0; i<files.size(); i++) {
            Part part = new FilePart(files.get(i).getName(), files.get(i));
            parts[i] = part;
        }

        MultipartRequestEntity entity = new MultipartRequestEntity(parts, connectionParams);

        post.setRequestEntity(entity);

        int statusCode = client.executeMethod(post);
        String response = post.getResponseBodyAsString();

        Log.v("Multipart "," "+response);
        if(statusCode == 200) {
            return response;
        }
    } catch (IOException e) {
        e.printStackTrace();
    } 
 return null;
}

You can also add the request and response timeout

client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000);
client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 10000);
0

I can recomend Ion library it use 3 dependences and you can find all three jar files at these two sites:
https://github.com/koush/ion#jars (ion and androidasync)

https://code.google.com/p/google-gson/downloads/list (gson)
try {
   Ion.with(this, "http://www.urlthatyouwant.com/post/page")
   .setMultipartParameter("field1", "This is field number 1")
   .setMultipartParameter("field2", "Field 2 is shorter")
   .setMultipartFile("imagefile",
        new File(Environment.getExternalStorageDirectory()+"/testfile.jpg"))
   .asString()
   .setCallback(new FutureCallback<String>() {
        @Override
        public void onCompleted(Exception e, String result) {
             System.out.println(result);
        }});
   } catch(Exception e) {
     // Do something about exceptions
        System.out.println("exception: " + e);
   }

this will run async and the callback will be executed in the UI thread once a response is received I strongly recomned that you go to the https://github.com/koush/ion for futher information

Alejandro Serret
  • 1,139
  • 15
  • 16
0

Here is a Simple approach if you are using the AOSP library Volley.

Extend the class Request<T> as follows-

public class MultipartRequest extends Request<String> {
    private static final String FILE_PART_NAME = "file";
    private final Response.Listener<String> mListener;
    private final Map<String, File> mFilePart;
    private final Map<String, String> mStringPart;
    MultipartEntityBuilder entity = MultipartEntityBuilder.create();
    HttpEntity httpentity;

    public MultipartRequest(String url, Response.ErrorListener errorListener,
                            Response.Listener<String> listener, Map<String, File> file,
                            Map<String, String> mStringPart) {
        super(Method.POST, url, errorListener);
        mListener = listener;
        mFilePart = file;
        this.mStringPart = mStringPart;
        entity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        buildMultipartEntity();
    }

    public void addStringBody(String param, String value) {
        mStringPart.put(param, value);
    }

    private void buildMultipartEntity() {
        for (Map.Entry<String, File> entry : mFilePart.entrySet()) {
            // entity.addPart(entry.getKey(), new FileBody(entry.getValue(), ContentType.create("image/jpeg"), entry.getKey()));
            try {
                entity.addBinaryBody(entry.getKey(), Utils.toByteArray(new FileInputStream(entry.getValue())), ContentType.create("image/jpeg"), entry.getKey() + ".JPG");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        for (Map.Entry<String, String> entry : mStringPart.entrySet()) {
            if (entry.getKey() != null && entry.getValue() != null) {
                entity.addTextBody(entry.getKey(), entry.getValue());
            }
        }
    }

    @Override
    public String getBodyContentType() {
        return httpentity.getContentType().getValue();
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            httpentity = entity.build();
            httpentity.writeTo(bos);
        } catch (IOException e) {
            VolleyLog.e("IOException writing to ByteArrayOutputStream");
        }
        return bos.toByteArray();
    }

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        Log.d("Response", new String(response.data));
        return Response.success(new String(response.data), getCacheEntry());
    }

    @Override
    protected void deliverResponse(String response) {
        mListener.onResponse(response);
    }
}

You can create and add a request like-

Map<String, String> params = new HashMap<>();
        params.put("name", name.getText().toString());
        params.put("email", email.getText().toString());
        params.put("user_id", appPreferences.getInt( Utils.PROPERTY_USER_ID, -1) + "");
        params.put("password", password.getText().toString());
        params.put("imageName", pictureName);
        Map<String, File> files = new HashMap<>();
        files.put("photo", new File(Utils.LOCAL_RESOURCE_PATH + pictureName));
        MultipartRequest multipartRequest = new MultipartRequest(Utils.BASE_URL + "editprofile/" + appPreferences.getInt(Utils.PROPERTY_USER_ID, -1), new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                // TODO Auto-generated method stub
                Log.d("Error: ", error.toString());
                FugaDialog.showErrorDialog(ProfileActivity.this);
            }
        }, new Response.Listener<String>() {
            @Override
            public void onResponse(String jsonResponse) {
                JSONObject response = null;
                try {
                    Log.d("jsonResponse: ", jsonResponse);
                    response = new JSONObject(jsonResponse);

                } catch (JSONException e) {
                    e.printStackTrace();
                }
                try {
                    if (response != null && response.has("statusmessage") && response.getBoolean("statusmessage")) {
                        updateLocalRecord();

                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                FugaDialog.dismiss();
            }

        }, files, params);
        RequestQueue queue = Volley.newRequestQueue(this);
        queue.add(multipartRequest);
Sanjeet A
  • 5,171
  • 3
  • 23
  • 40
0

For posterity, I didn't see okhttp mentioned. Related post.

Basically you build up the body using a MultipartBody.Builder, and then post this in a request.

Example in kotlin:

    val body = MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart(
                "file", 
                file.getName(),
                RequestBody.create(MediaType.parse("image/png"), file)
            )
            .addFormDataPart("timestamp", Date().time.toString())
            .build()

    val request = Request.Builder()
            .url(url)
            .post(body)
            .build()

    httpClient.newCall(request).enqueue(object : okhttp3.Callback {
        override fun onFailure(call: Call?, e: IOException?) {
            ...
        }

        override fun onResponse(call: Call?, response: Response?) {
            ...
        }
    })
Community
  • 1
  • 1
RecencyEffect
  • 736
  • 7
  • 18