3

我正在尝试使用以下代码将文件上传到休息 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: Out of memory on a 67102090-byte allocation.

4

1 回答 1

4

分析代码,Android 的 Spring 似乎在发送数据之前缓冲了它的数据——这就是你的 OOE 的原因。但是有一个技巧(但到目前为止,我已经使其仅适用于上面的 API 级别 9):您可以禁用其连接工厂的缓冲,但前提是 RestTemplate 没有ClientHttpRequestInterceptor设置列表(现在这有多愚蠢? ) - 你很幸运,因为你没有设置一个。因此,在您的情况下,情况非常简单,只需factory.setBufferRequestBody(false);在实例化后调用即可。

于 2013-08-07T14:11:46.533 回答