安卓Spring文件上传内存溢出

3

我试图使用以下代码将文件上传到rest api。这段代码适用于大小不超过20MB的文件,但更大的文件会导致OutOfMemoryError。我正在尝试对请求进行分块,并使用多部分表单请求,以便无需在内存中保留整个文件,但也许块太大了?如有帮助,不胜感激。

    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;

错误信息: dalvikvm-heap: 尝试分配 67102090 字节的内存空间失败,可能是由于内存不足所致。

https://dev59.com/yWkw5IYBdhLWcg3wzdzZ - KOTIOS
@Stacks28 这个能否使用Spring来实现,而不是使用HTTPURLConnection呢? - Ryan S
我没有和Spring一起工作过,所以无法给你建议。 - KOTIOS
检查一下这个库(http://androidcustomviews.com/portfolio/simpl3r/),也许你会得到一些帮助。 - Girish Bhutiya
1个回答

4
分析代码后发现,Spring for Android在发送数据之前会缓存数据,这就是为什么出现OOE的原因。但是有一个技巧(目前只能在API 9及以上版本中使用),你可以禁用其连接工厂的缓冲,但前提是RestTemplate没有设置ClientHttpRequestInterceptor列表(这多么愚蠢啊!)- 幸运的是,你没有设置它。所以在你的情况下,情况非常简单,只需在实例化后调用factory.setBufferRequestBody(false);即可。

@gunar,你救了我一命。我欠你一个人情。 - francis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接