当使用Jersey客户端将大文件作为InputStream放置时,似乎文件的全部内容在被发送到服务器之前被缓冲到内存中。这会导致大文件出现问题,因为JVM的堆空间不足。如何在Jersey客户端中阻止此行为?发送数据时,服务器端的JAX-RS资源方法似乎没有这个问题。
例如:
WebResource dataUploadResource = buildDataUploadResource();
dataUploadResource.type(getMimeType()).put(getLargeInputStream());
答案 0 :(得分: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库不支持指定大小。