3

I am trying to use the following code to upload a file to a rest api. This code works fine for files up to around 20MB, but bigger files will give an OutOfMemoryError. I am trying to chunk the request and use a multipart-form request so that I don't have to keep the whole file in memory, but maybe the chunks are too big? Any help is greatly appreciated.

    final File file = new File(filePath);
    HttpHeaders header = new HttpHeaders();
    header.add("x-haiku-auth", HaikuAPI.getAuthHeader());
    header.setContentType(MediaType.MULTIPART_FORM_DATA);
    UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(
            "https://" + HaikuAPI.getDomain() + "/api/assignments")
            .pathSegment(assignmentID + "", "submit");

    URI url = builder.build().toUri();

    MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();

    parts.add("message[subject]", "Assignment Completed");
    parts.add("message[body]", message);
    parts.add("message[assignment_id]", assignmentID + "");
    Uri uri = Uri.fromFile(file);
    InputStreamResource res = new InputStreamResource(context.getContentResolver().openInputStream(uri)) {
        @Override
        public String getFilename() throws IllegalStateException {
            return file.getName();
        }

        @Override
        public long contentLength() throws IOException {
            return file.length();
        }
    };
    parts.add("files[][file]", res);
    parts.add("files[][filename]", file.getName());
    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    factory.setChunkSize(1024);
    RestTemplate restTemplate = new RestTemplate(factory);
    restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
    HttpEntity<Object> request = new HttpEntity<Object>(parts, header);
    restTemplate.postForLocation(url, request);
    Log.e("f", "finished");
    return null;

Error: dalvikvm-heap: Out of memory on a 67102090-byte allocation.

4
  • stackoverflow.com/questions/9630430/… Commented Aug 7, 2013 at 5:06
  • @Stacks28 Is this possible to do using Spring instead of HTTPURLConnection? Commented Aug 7, 2013 at 5:18
  • i hvnt worked with spring buddy so could not suggest you Commented Aug 7, 2013 at 5:22
  • check this library may be you get some help. Commented Aug 7, 2013 at 5:43

1 Answer 1

4

Analyzing the code, it seems Spring for Android buffers its data before sending it - that's why your OOE. There is a trick however (but so far I've made it possible to work only for API level 9 above): you can disable the buffering for its connection factory but ONLY if the RestTemplate has no ClientHttpRequestInterceptor list set (now how stupid is that ?) - lucky you as you didn't set one. So in your case the situation is very simple, just call factory.setBufferRequestBody(false); after you've instantiated it.

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

1 Comment

@gunar, you saved the day. I owe you one

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.