7

Im trying to POST a file to an API of mine along with other parameters.

Eg. POST /media with the parameters

filename = 'test.png'

file = -the-actual-file-

I can do this successfully with Postman (using form-data), so the api side of things are fine.

Here is my android code using HttpURLConnection:

nameValuePairs.add(new BasicNameValuePair("filename", "test.png"));

URL object = new URL(url);
HttpURLConnection connection = (HttpURLConnection) object.openConnection();
connection.setReadTimeout(60 * 1000);
connection.setConnectTimeout(60 * 1000);
String auth = username+":"+password;
    byte[] data = auth.getBytes();
    String encodeAuth = "Basic " + Base64.encodeToString(data, Base64.DEFAULT);
    connection.setDoInput(true);
    connection.setDoOutput(true);
    connection.setUseCaches(false);
    connection.setRequestProperty("Authorization", encodeAuth);
    connection.setRequestProperty("Accept", ACCEPT);
    connection.setRequestMethod("POST");
    connection.setRequestProperty("ENCTYPE", "multipart/form-data");
    connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
    dataOutputStream = new DataOutputStream(connection.getOutputStream());
    writer = new BufferedWriter(new OutputStreamWriter(dataOutputStream, "UTF-8"));
    writer.write(getQuery(nameValuePairs));

     writer.write("&file=" + "image.jpg");
     writer.write
     File file = getFile(item);
     if (file == null) {
      Log.e("uploadFile", "Source File not exist " );
     } else {
      addFilePart("file", file);
     }
    }
    writer.flush();
    writer.close();
    dataOutputStream.close();


    connection.connect();
2

2 Answers 2

27

Android multipart upload.

public String multipartRequest(String urlTo, Map<String, String> parmas, String filepath, String filefield, String fileMimeType) throws CustomException {
        HttpURLConnection connection = null;
        DataOutputStream outputStream = null;
        InputStream inputStream = null;

        String twoHyphens = "--";
        String boundary = "*****" + Long.toString(System.currentTimeMillis()) + "*****";
        String lineEnd = "\r\n";

        String result = "";

        int bytesRead, bytesAvailable, bufferSize;
        byte[] buffer;
        int maxBufferSize = 1 * 1024 * 1024;

        String[] q = filepath.split("/");
        int idx = q.length - 1;

        try {
            File file = new File(filepath);
            FileInputStream fileInputStream = new FileInputStream(file);

            URL url = new URL(urlTo);
            connection = (HttpURLConnection) url.openConnection();

            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);

            connection.setRequestMethod("POST");
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("User-Agent", "Android Multipart HTTP Client 1.0");
            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=\"" + filefield + "\"; filename=\"" + q[idx] + "\"" + lineEnd);
            outputStream.writeBytes("Content-Type: " + fileMimeType + lineEnd);
            outputStream.writeBytes("Content-Transfer-Encoding: binary" + lineEnd);

            outputStream.writeBytes(lineEnd);

            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            buffer = new byte[bufferSize];

            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
            while (bytesRead > 0) {
                outputStream.write(buffer, 0, bufferSize);
                bytesAvailable = fileInputStream.available();
                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);
            }

            outputStream.writeBytes(lineEnd);

            // Upload POST Data
            Iterator<String> keys = parmas.keySet().iterator();
            while (keys.hasNext()) {
                String key = keys.next();
                String value = parmas.get(key);

                outputStream.writeBytes(twoHyphens + boundary + lineEnd);
                outputStream.writeBytes("Content-Disposition: form-data; name=\"" + key + "\"" + lineEnd);
                outputStream.writeBytes("Content-Type: text/plain" + lineEnd);
                outputStream.writeBytes(lineEnd);
                outputStream.writeBytes(value);
                outputStream.writeBytes(lineEnd);
            }

            outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);


            if (200 != connection.getResponseCode()) {
                throw new CustomException("Failed to upload code:" + connection.getResponseCode() + " " + connection.getResponseMessage());
            }

            inputStream = connection.getInputStream();

            result = this.convertStreamToString(inputStream);

            fileInputStream.close();
            inputStream.close();
            outputStream.flush();
            outputStream.close();

            return result;
        } catch (Exception e) {
            logger.error(e);
            throw new CustomException(e);
        }

    }

    private String convertStreamToString(InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

Calling code:

//setup params
Map<String, String> params = new HashMap<String, String>(2);
        params.put("foo", hash);
        params.put("bar", caption);

String result = multipartRequest(URL_UPLOAD_VIDEO, params, pathToVideoFile, "video", "video/mp4");
//next parse result string

Ref Link https://stackoverflow.com/a/26145565/1143026

Sign up to request clarification or add additional context in comments.

3 Comments

Works like a charm!
It is better to mark a question as a duplicate, instead of copy-pasting an answer.
how the code would look like , if i am supposed to add one more field ...say password
0

Accepted answer needs a small update if you are using nanoHttpd for server end., as this issue took a lot of debugging time.. and had to use the below timeline source code from insomnia to understand the problem. Insomnia screenshot for multipart upload timeline just avoid using (//comment out) outputStream.writeBytes("Content-Type: text/plain" + lineEnd); as this ends up setting the post parameters to null

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.