12

当使用Jersey客户端将大文件设置为 InputStream时,文件的全部内容似乎在发送到服务器之前被缓冲到内存中。当 JVM 用完堆空间时,这会导致大文件出现问题。如何防止 Jersey 客户端出现这种行为?服务器端的 JAX-RS 资源方法在发送数据时似乎没有这个问题。

例如:

WebResource dataUploadResource = buildDataUploadResource();
dataUploadResource.type(getMimeType()).put(getLargeInputStream());
4

1 回答 1

13

为了防止这种行为,您需要将 Jersey 客户端配置为对请求使用分块编码1 。这消除了设置 Content-Length 标头的需要,并且将从提供的 InputStream 流式传输,而无需缓冲内存中的全部内容。

默认情况下,Jersey 使用 JDK 的 HttpURLConection 类来处理 HTTP 请求和响应。不幸的是,这有一些与分块编码传输相关的错误。幸运的是,Jersey 有扩展点以允许使用不同的 HTTP 客户端实现。一种这样的实现是基于 Apache Http Client 2的。

存在两种 apache htpp 客户端处理程序实现,一种支持现已停产的 3.x 版本,另一种使用较新的 4.x 版本。对于我们的项目,我们使用了基于旧 (3.1) 版本的实现。该库在 Maven Central 中的“contribs”子组下可用。

<dependency>
    <groupId>com.sun.jersey.contribs</groupId>
    <artifactId>jersey-apache-client</artifactId>
    <version>1.14</version>
</dependency>

接下来你必须初始化你的 Jersey 客户端以使用新的实现:

Client jerseyClient = ApacheHttpClient.create(getClientConfig());

为了启用分块编码,您必须在客户端配置上设置分块编码大小,因为默认情况下未启用它:

private ClientConfig getClientConfig() {
   ClientConfig config = new DefaultClientConfig();

   config.getProperties().put(
            DefaultApacheHttpClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 0);
   return config;
}

只要这个属性不是null,就会使用分块编码。事实上,1.14 版忽略了编码大小,因为底层 apache commons-httpclient 库不支持指定大小。

于 2012-06-24T10:52:29.067 回答