2

Good day fellow developers.

I'm busy for android to upload images from a app.
I also got it working (code will follow below).
But when i send large images (10 megapixels) my app crashes with an out-of-memory exception.
A solution for this is to use compression but what if i want to send the full size image?
I think perhaps something with a stream but i'm not familair with streams. Perhaps urlconnection might help to but i really have no idea.

I give the filename the name File[0 to 9999].jpg The post value with the image date is called Filedata I give a UID for the post value dropboxid

The code below works but i would love to solve my problem that prevents me from sending high res images.

kind regards

try
{
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bitmap.compress(CompressFormat.JPEG, 100, bos);
    byte[] data = bos.toByteArray();

    HttpPost postRequest = new HttpPost(URL_SEND);

    ByteArrayBody bab = new ByteArrayBody(data, "File" + pad(random.nextInt(9999) + 1) + ".jpg");
    MultipartEntity reqEntity = new multipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
    reqEntity.addPart("Filedata", bab);
    reqEntity.addPart("dropboxId", new StringBody(URLEncoder.encode(uid)));
    postRequest.setEntity(reqEntity);

    HttpResponse response = httpClient.execute(postRequest);
    BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
    String sResponse;
    StringBuilder s = new StringBuilder();

    while((sResponse = reader.readLine()) != null)
    {
        s = s.append(sResponse);
    }

    if(d) Log.i(E, "Send response:\n" + s);
}
catch (Exception e)
{
    if(d) Log.e(E, "Error while sending: " + e.getMessage());
    return ERROR;
}
user1195015
  • 102
  • 1
  • 8

1 Answers1

3

When using ByteArrayOutputStream and then calling #toByteArray() you've effectively doubled the amount of memory the JPEG is using. ByteArrayOutputStream keeps an internal array with the encoded JPEG and when you call #toByteArray() it allocates a new array & copies the data from the internal buffer.

Consider encoding large bitmaps to a temporary file & using FileOutputStream and FileInputStream to encode and send the image.

Without "uploading" - your app survives "nicely" with the just the huge bitmap in memory I assume?

Edit: FileBody

File img = new File(this is where you put the path of your image)
ContentBody cb = new FileBody(img, "File" + pad(random.nextInt(9999) + 1) + ".jpg", "image/jpg", null);
MultipartEntity reqEntity = new multipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("Filedata", cb);
reqEntity.addPart("dropboxId", new StringBody(URLEncoder.encode(uid)));
Jens
  • 16,853
  • 4
  • 55
  • 52
  • In my app i store only a reference to the file. So the file is already stored (on the sd card). Only when i start uploading i fetch the bitmap from it. My main problem is that i have no idea how i can get from that file the inputstream and convert it to an outputstream that i can post with my entity. The bitmap code bitmap = BitmapFactory.decodeFile(path); So here i have to do something like ByteArrayBody bab = fileinputstream(path)? – user1195015 Apr 27 '12 at 13:00
  • So.. why would you fetch the bitmap? Is the source file a PNG and the web server only accepts PNG? Otherwise - just upload the file you already have - re-encoding a JPEG like that is likely to just introduces more wacky artifacts in the image. **Edit**: You've imported some extra Apache libs correct? In that case you should have the `FileBody` class. Can you use that – Jens Apr 27 '12 at 13:04
  • I can send almost any file type i like. But i still don't got a clue on how to get the bytes from the file. But the idea is good so i think i'll go google on that. Or if you have an quick example it would be nice. If i find something i'll post it. Thanks for the advice – user1195015 Apr 27 '12 at 13:06
  • Well, you can implement your own `ContentBody`, but just using `FileBody` instead of `ByteArrayBody` should work for you. – Jens Apr 27 '12 at 13:07