26

My upload code as below:

String end = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
try {
    URL url = new URL(ActionUrl);
    HttpURLConnection con = (HttpURLConnection) url.openConnection();
    con.setDoInput(true);
    con.setDoOutput(true);
    con.setUseCaches(false);
    con.setRequestMethod("POST");
    con.setRequestProperty("Connection", "Keep-Alive");
    con.setRequestProperty("Accept", "text/*");
    con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
    DataOutputStream ds = new DataOutputStream(con.getOutputStream());
    ds.writeBytes(twoHyphens + boundary + end);
    ds.writeBytes("Content-Disposition: form-data;" + "name=\"folder\"" + end + end);
    ds.write(SavePath.getBytes("UTF-8"));
    ds.writeBytes(end);
    ds.writeBytes(twoHyphens + boundary + end);
    ds.writeBytes("Content-Disposition: form-data;" + "name=\"Filedata\"; filename=\"");
    ds.write(FileName.getBytes("UTF-8"));
    ds.writeBytes("\"" + end);
    ds.writeBytes(end);
    FileInputStream fStream = new FileInputStream(uploadFilepath+""+FileName);
    int bufferSize = 1024;
    byte[] buffer = new byte[bufferSize];
    int length = -1;
    int pro = 0;
    while((length = fStream.read(buffer)) != -1) {
        ds.write(buffer, 0, length);
    }       
    ds.writeBytes(end);
    ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
    fStream.close();
    ds.flush();
    InputStream is = con.getInputStream();
    int ch;
    StringBuffer b = new StringBuffer();
    while((ch = is.read()) != -1) {
        b.append((char)ch);
    }
    ds.close();
}
catch(Exception e) {
    e.printStackTrace();
}

While smaller than 16 mb, it upload success. But while it more than 16 mb, the "OutOfMemory" error show. How to avoid the outofmemory error?

Sufian
  • 6,405
  • 16
  • 66
  • 120
brian
  • 6,802
  • 29
  • 83
  • 124

3 Answers3

70

Did you try using

con.setChunkedStreamingMode(1024);

This will help you to chunk your data into specific size, so that you need not keep your entire file in the memory.

UPDATE:

Try using the below method. I use this method to upload a 80 mb file without Exception.

public String sendFileToServer(String filename, String targetUrl) {
    String response = "error";
    Log.e("Image filename", filename);
    Log.e("url", targetUrl);
    HttpURLConnection connection = null;
    DataOutputStream outputStream = null;
    // DataInputStream inputStream = null;

    String pathToOurFile = filename;
    String urlServer = targetUrl;
    String lineEnd = "\r\n";
    String twoHyphens = "--";
    String boundary = "*****";
    DateFormat df = new SimpleDateFormat("yyyy_MM_dd_HH:mm:ss");

    int bytesRead, bytesAvailable, bufferSize;
    byte[] buffer;
    int maxBufferSize = 1 * 1024;
    try {
        FileInputStream fileInputStream = new FileInputStream(new File(
                pathToOurFile));

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

        // Allow Inputs & Outputs
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(false);
        connection.setChunkedStreamingMode(1024);
        // Enable POST method
        connection.setRequestMethod("POST");

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

        outputStream = new DataOutputStream(connection.getOutputStream());
        outputStream.writeBytes(twoHyphens + boundary + lineEnd);

        String connstr = null;
        connstr = "Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
                + pathToOurFile + "\"" + lineEnd;
        Log.i("Connstr", connstr);

        outputStream.writeBytes(connstr);
        outputStream.writeBytes(lineEnd);

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

        // Read file
        bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        Log.e("Image length", bytesAvailable + "");
        try {
            while (bytesRead > 0) {
                try {
                    outputStream.write(buffer, 0, bufferSize);
                } catch (OutOfMemoryError e) {
                    e.printStackTrace();
                    response = "outofmemoryerror";
                    return response;
                }
                bytesAvailable = fileInputStream.available();
                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);
            }
        } catch (Exception e) {
            e.printStackTrace();
            response = "error";
            return response;
        }
        outputStream.writeBytes(lineEnd);
        outputStream.writeBytes(twoHyphens + boundary + twoHyphens
                + lineEnd);

        // Responses from the server (code and message)
        int serverResponseCode = connection.getResponseCode();
        String serverResponseMessage = connection.getResponseMessage();
        Log.i("Server Response Code ", "" + serverResponseCode);
        Log.i("Server Response Message", serverResponseMessage);

        if (serverResponseCode == 200) {
            response = "true";
        }

        String CDate = null;
        Date serverTime = new Date(connection.getDate());
        try {
            CDate = df.format(serverTime);
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("Date Exception", e.getMessage() + " Parse Exception");
        }
        Log.i("Server Response Time", CDate + "");

        filename = CDate
                + filename.substring(filename.lastIndexOf("."),
                        filename.length());
        Log.i("File Name in Server : ", filename);

        fileInputStream.close();
        outputStream.flush();
        outputStream.close();
        outputStream = null;
    } catch (Exception ex) {
        // Exception handling
        response = "error";
        Log.e("Send file Exception", ex.getMessage() + "");
        ex.printStackTrace();
    }
    return response;
}
Andro Selva
  • 53,910
  • 52
  • 193
  • 240
  • I try add to below of line con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);, but it upload fail for all files. – brian Mar 09 '12 at 07:41
  • 1
    The error java.io.FileNotFoundException: http://ip/web/jquery/uploader/uploadify.php showed. – brian Mar 09 '12 at 07:42
  • * For anyone using this excellent code with App Engine: On the line building connstr, add a space before filename= (...name=\"uploadedfile\"; filename=...) – OferR Nov 28 '12 at 15:58
  • @AndroSelva could you have a look at [mypost](http://stackoverflow.com/questions/15243674/outofmemoryexception-while-trying-to-send-large-json-data-to-server-in-android?noredirect=1#comment21512267_15243674) please. I am also facing the same problem will this work for me as well. Thanks – vinothp Mar 06 '13 at 18:45
  • 1
    @AndroSelva: If I want to add more parts to the multipart entity? I just add newlines to the outputstream and add the data that I want to? lets say I want to add a json string with the name 'json', and another file. – meh Mar 28 '13 at 14:19
  • can you please give me the server side script for this code ? – Jamil Jun 22 '14 at 13:52
  • can any one please give me server side script ? plz – Jamil Jun 22 '14 at 14:05
  • I believe that as a Server Code you can use this: ` ` But please make sure that your server does not respond `NULL` to this request: ` ini_get('upload_tmp_dir'); ` because thats where your files will be uplaoded, and above code will move it from the tmp directory to the uploads/ – Dawid Czerwinski Aug 07 '14 at 12:24
  • You should really refactor this, anyways I'm giving it a try will +1 if it works fine. – Mathijs Segers Feb 16 '15 at 15:14
  • To @AndroSelva can you please share a targetURL sample code for my quick reference. As I have tried but I think my targetURL is incorrect or missing something. – Milan Sheth Jan 08 '16 at 04:06
  • I have the same problem having `java.lang.OutOfMemoryError` but `setChunkedStreamingMode(1024);` and my Byte[1024] does not solve my problem. – user3502626 Apr 16 '16 at 19:02
  • 1
    i put setChunkedStreamingMode(1024); in my code and i'm getting: HTTP/1.1 400 Bad RequestContent-Length: 11Content-Type: text/plainBad Request – Fábio Filho May 01 '16 at 17:03
  • hey is it possible to get the php counterpart for this – user2692997 Jul 19 '16 at 11:11
  • @AndroSelva your code only works if I remove `connection.setChunkedStreamingMode(1024);` but after removing this I can't upload large files. What to do? – Pablo Escobar May 20 '17 at 04:47
1

if Server accept chunked mode, you can use

((HttpURLConnection) con).setChunkedStreamingMode(chunkLength)

otherwise you can use

((HttpURLConnection) con).setChunkedStreamingMode(0);

or

/* compute first your request content length
   contentLength = formBodyLength + yourFileSize
*/
con.setRequestProperty("Content-Length", String.valueOf(contentLength));
((HttpURLConnection) con).setFixedLengthStreamingMode(contentLength);

finally... send what you want

tdjprog
  • 706
  • 6
  • 11
-5
bitmap=Bitmap.createScaledBitmap(bitmap, 100, 100, true);

ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); //compress to format you want.
byte [] byte_arr = stream.toByteArray();  
String image_str = Base64.encodeBytes(byte_arr);

Best Way I tried it was successful for me!!!

Kushal Sharma
  • 5,978
  • 5
  • 25
  • 41
rajlaxmi_jagdale
  • 1,370
  • 15
  • 16
  • link to compress method: https://developer.android.com/reference/android/graphics/Bitmap.html – chance Oct 17 '17 at 13:17
  • 1
    the question is not about images, it's about general files – Ricardo A. Jun 06 '19 at 19:58
  • While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. –  May 05 '22 at 00:56