2

I am trying to upload a file to a server via HTTP POST from my device. I have two method upload1 and upload2.

Upload1 uses the HttpPost class and it works, but with bigger files it throws out of memory exception.

Upload2 uses HttpURLConnection and it does not work. (I get BAD REQUEST message from the server.) I want upload2 to work, because it uses stream to send the data and throws no out of memory exception. I looked at the packages in wireshark, the headers are seems to be the same, however the length with upload1 is 380, with upload2 is only 94. What could be the problem?

private void upload1(File file) {

        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(url + "?recname="
                    + fileName);

            // ///////////////////////////////////////
            String lineEnd = "\r\n";
            String twoHyphens = "--";
            String boundary = "---------------------------This is the boundary";

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            DataOutputStream dos = new DataOutputStream(baos);

            FileInputStream fin = new FileInputStream(file);

            byte audioData[] = new byte[(int) file.length()];

            fin.read(audioData);
            fin.close();

            // Send a binary file
            dos.writeBytes(twoHyphens + boundary + lineEnd);

            dos.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\""
                    + fileName + "\"" + lineEnd);
            dos.writeBytes("Content-Type: audio/mp4" + lineEnd);
            dos.writeBytes("Content-Transfer-Encoding: binary" + lineEnd);
            dos.writeBytes(lineEnd);
            dos.write(audioData);
            dos.writeBytes(lineEnd);
            dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
            dos.flush();
            dos.close();

            ByteArrayInputStream content = new ByteArrayInputStream(
                    baos.toByteArray());
            BasicHttpEntity entity = new BasicHttpEntity();
            entity.setContent(content);

            entity.setContentLength(baos.toByteArray().length);

            httppost.addHeader("Content-Type", "multipart/form-data; boundary="
                    + boundary);

            httppost.setEntity(entity);

            // //////////////////////////////////

            HttpResponse response = httpclient.execute(httppost);

            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    response.getEntity().getContent(), "UTF-8"));
            StringBuilder builder = new StringBuilder();

            for (String line = null; (line = reader.readLine()) != null;) {
                builder.append(line).append("\n");
            }

            reader.close();
            message = builder.toString();
            System.out.println(message);

        } catch (UnknownHostException e) {
            message = "Error! Server is unreachable. Check you internet connection!";
        } catch (Exception e) {
            message = "error: " + e.toString();
        }

    }

/////////////////////////////////////////////////////////////////////////////////////////

private void upload2(File file) {

        HttpURLConnection connection = null;

        String pathToOurFile = file.getPath();
        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary = "---------------------------This is the boundary";

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

        try {

            fileInputStream = new FileInputStream(new File(pathToOurFile));

            URL server_url = new URL(url+ "?recname="
                    + fileName);
            connection = (HttpURLConnection) server_url.openConnection();

            // Allow Inputs & Outputs
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);

            // Enable POST method
            connection.setRequestMethod("POST");

            String bodyHeader = twoHyphens
                    + boundary
                    + lineEnd
                    + "Content-Disposition: form-data; name=\"file\";filename=\""
                    + fileName + "\"" + lineEnd + "Content-Type: audio/mp4"
                    + lineEnd + "Content-Transfer-Encoding: binary" + lineEnd
                    + lineEnd + twoHyphens + boundary + twoHyphens ;

            byte[] bodyHeaderAray = bodyHeader.getBytes();

            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("Content-Type",
                    "multipart/form-data;boundary=" + boundary);
            connection.setRequestProperty("Expect", "100-continue");

            // Content-Length
            int bodyHeaderSize = (int) file.length() + bodyHeaderAray.length;
            System.out.println("body header size: " + bodyHeaderSize);
            // connection.setFixedLengthStreamingMode(bodyHeaderSize);

            outputStream = new DataOutputStream(connection.getOutputStream());
            outputStream.writeBytes(twoHyphens + boundary + lineEnd);
            outputStream
                    .writeBytes("Content-Disposition: form-data; name=\"file\";filename=\""
                            + fileName + "\"");
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes("Content-Type: audio/mp4" + lineEnd);
            outputStream.writeBytes("Content-Transfer-Encoding: binary"
                    + lineEnd);

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

            // Read file
            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);
            outputStream.writeBytes(twoHyphens + boundary + twoHyphens
                    + lineEnd);

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

            // Responses from the server (code and message)
            int serverResponseCode = connection.getResponseCode();
            String serverResponseMessage = connection.getResponseMessage();

            message = serverResponseMessage;

        } catch (Exception ex) {
            System.out.println(ex);
        }
    }

2 Answers 2

3

According to the Problems you are getting to upload the files. you should use Multipart mechanism to upload the files to server.

    httpclient-4.1.jar
    httpcore-4.1.jar
    httpmime-4.1.jar
    apache-mime4j-0.6.1.jar

For that you need to add couple of libraries into your project and use it for HTTP connection and file data.

    private boolean uploadFile(File mFile) {
            boolean success = true;
            String filename = mFile.getName();
            MultipartEntity data_to_send = new MultipartEntity(
                    HttpMultipartMode.BROWSER_COMPATIBLE);
            try {
                data_to_send.addPart(
                        "name",
                        new StringBody(
                                filename.substring(filename.lastIndexOf("/") + 1)));
                data_to_send.addPart("fileData", new FileBody(mFile));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            try {
                String responseData = ConsumeWebService.sendRequest(data_to_send,
                        Global.BASE_URL + serviceUrl);
                if (TextUtils.isEmpty(responseData)
                        || responseData.equals(ConsumeWebService.ERROR_CODE)) {
                    success = false;
                }
            } catch (Exception e) {
                success = false;
                e.printStackTrace();
            }
            return success;
        }


public static String sendRequest(MultipartEntity data, String url) {
        String response = "";
        response = postData(url, data);
        return response;
    }


private static String postData(String url, MultipartEntity data) {
        String strResponse = "";

        try {
            Log.d(Global.TAG, "Post URL is " + url);
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(data);
            strResponse = httpClient.execute(httpPost,
                    new BasicResponseHandler());
        } catch (UnsupportedEncodingException e) {
            strResponse = ERROR_CODE;
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            strResponse = ERROR_CODE;
            e.printStackTrace();
        } catch (IOException e) {
            strResponse = ERROR_CODE;
            e.printStackTrace();
        }
        return strResponse;
    }
Sign up to request clarification or add additional context in comments.

3 Comments

I don't know these librarries. Does MultipartEntity takes care of streaming the file? I am worried about getting an aout of memory exception with this library again.
This libraries you can download by simply googling. This libraries are powerful enough to handle out of memory. so do not worry on that part
MultipartEntity is currently deprecated. Apache suggests to use MultipartEntityBuilder instead (hc.apache.org/httpcomponents-client-4.3.x/httpmime/examples/org/…) but I haven't managed to make this work for Android yet.
0

You can build by your own your POST Request by following this w3.org docs about forms.

I think in upload2 you are missing one lineEnd where you do:

....
outputStream.writeBytes("Content-Transfer-Encoding: binary"
                + lineEnd);

After this, you have to transmit the data and it takes two lineEnds before actual data, so it should be:

....
outputStream.writeBytes("Content-Transfer-Encoding: binary"
                + lineEnd + lineEnd);


For reading files and place them in multipart/form-data structure, I suggest you this way that works for me:

FileInputStream fileInputStream=new FileInputStream(file);
byte[] bytes= new bytes[fileInputStream.getChannel().size()];
fileInputStream.read(bytes);
fileInputStream.close();
outputStream.write(bytes);
outputStream.writeBytes(lineEnd);

Hope it helps.

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.