最近我从 Apache Commons Http Client 3.x 迁移到新的 Apache 4.x http 客户端。一切都被替换,比如多线程 Http 客户端连接管理器被替换为 PoolingHttpClientManager。除了上传大文件外,一切正常。它进入一个接受路径和输入流的 put 方法,当我尝试上传大文件时它失败。只有当我将程序放在云上时才会出现这种情况,如果我将其创建为 exe 文件并安装它,并且在 eclipse 环境中它也可以正常工作。我正在使用 tomcat 的 webdav 功能,并且在云中 webdav 服务器放置在代理后面。 以下是用于上传文件的putMethod的代码
HttpPut method = null;
try
{
method = new HttpPut(this.encodePath(path));
setProxy(method);
}
catch (MalformedURLException | URISyntaxException ex)
{
throw new HttpURIException();
}
String contentType = getGetContentType();
if ((contentType != null) && (contentType.length() > 0))
{
method.setHeader("Content-Type", contentType);
}
InputStreamEntity ise = new InputStreamEntity(inputStream);
ise.setChunked(true);
ise.setContentType(contentType);
BufferedHttpEntity bhe = new BufferedHttpEntity(ise);
method.setEntity(bhe);
try
{
HttpResponse response = this.client.execute(method);
return (response.getStatusLine().getStatusCode() >= 200) && (response.getStatusLine().getStatusCode() < 300);
}
finally
{
method.releaseConnection();
}
}
以下是错误的堆栈跟踪
ERROR - FileUploadHandler - IO Error while file upload. java.net.SocketException: Connection reset by peer (Write failed) at java.net.SocketOutputStream.socketWrite0(Native Method) ~[?:?] at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110) ~[?:?] at java.net.SocketOutputStream.write(SocketOutputStream.java:150) ~[?:?] at org.apache.http.impl.io.SessionOutputBufferImpl.streamWrite(SessionOutputBufferImpl.java:124) ~[httpcore-4.4.13.jar:4.4.13] at org.apache.http.impl.io.SessionOutputBufferImpl.write(SessionOutputBufferImpl.java:160) ~[httpcore-4.4.13.jar:4.4.13] at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:113) ~[httpcore-4.4.13.jar:4.4.13] at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:120) ~[httpcore-4.4.13.jar:4.4.13] at org.apache.http.entity.BufferedHttpEntity.writeTo(BufferedHttpEntity.java:105) ~[httpcore-4.4.13.jar:4.4.13] at org.apache.http.impl.DefaultBHttpClientConnection.sendRequestEntity(DefaultBHttpClientConnection.java:156) ~[httpcore-4.4.13.jar:4.4.13] at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:238) ~[httpcore-4.4.13.jar:4.4.13] at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123) ~[httpcore-4.4.13.jar:4.4.13] at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272) ~[httpclient-4.5.13.jar:4.5.13] at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) ~[httpclient-4.5.13.jar:4.5.13] at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) ~[httpclient-4.5.13.jar:4.5.13] at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[httpclient-4.5.13.jar:4.5.13] at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) ~[httpclient-4.5.13.jar:4.5.13] at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) ~[httpclient-4.5.13.jar:4.5.13] at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108) ~[httpclient-4.5.13.jar:4.5.13] at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) ~[httpclient-4.5.13.jar:4.5.13]
在最新的客户端中我使用以下方式创建新客户端
PoolingHttpClientConnectionManager conManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(40);
connectionManager.setDefaultMaxPerRoute(20);
RequestConfig defaultRequestConfig = RequestConfig.custom().setConnectTimeout(CONNECTION_TIMEOUT).build();
SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(SO_TIMEOUT).build();
HttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(HTTPMETHOD_RETRY_COUNT, false);
HttpClientBuilder clientBuilder = HttpClients.custom().useSystemProperties().setConnectionManager(conManager).setDefaultRequestConfig(defaultRequestConfig).setDefaultSocketConfig(socketConfig).setRetryHandler(retryHandler);
credentials = new UsernamePasswordCredentials(userName, password);
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(getAuthScope(aHttpUrl), credentials);
clientBuilder.setDefaultCredentialsProvider(credentialsProvider);
boolean shouldUseProxy = isProxy(aConfig);
String proxyHost = System.getProperty(PROPERTY_PROXY_HOST);
if (shouldUseProxy)
{
String proxyPort = System.getProperty(PROPERTY_PROXY_PORT, "80");
HttpHost proxyHosts = new HttpHost(proxyHost, Integer.parseInt(proxyPort));
RequestConfig config = RequestConfig.copy(defaultRequestConfig).setProxy(proxyHosts).build();
clientBuilder.setDefaultRequestConfig(config);
}
有什么我应该添加或修改的吗? 或者我应该更改代理服务器的一些超时设置? 通过代码,我将超时设置为 5000,重试次数设置为 3。
使用与旧 http 客户端相同的配置。
我尝试了各种修改输入流的方法,并尝试实现自定义输入流。
它的工作原理是在方法执行时修改代码。您可以传递一个上下文变量,该变量可以帮助您在方法执行时进行身份验证。