HttpURLConnection getInputStream:180秒后总是超时

时间:2015-09-08 06:25:00

标签: java sockets inputstream httpurlconnection

我试图以这种方式在非常慢的连接上下载文件:

    java.net.URL url = new URL("https://X.X.X.X:8443/path/2f6b88cf2b70ee933197edfc9627a9bc/");
    HttpURLConnection connection = (HttpURLConnection)  url.openConnection();
    connection.setRequestMethod("GET");
    connection.setDoOutput(true);
    connection.setConnectTimeout(240 * 1000);
    connection.setReadTimeout(240 * 1000);
    long start = System.currentTimeMillis();
    Files.copy(connection.getInputStream(), new File("test.zip").toPath());
    System.out.println("Time: "+((System.currentTimeMillis() - start) / 1000) + " sec.");

我注意到由于某些原因(本机Windows套接字超时?)它总是在 180 秒下载后中断,没有任何异常。

setConnectTimeout(...)或setReadTimeout(...)中设置的超时没有帮助。

我尝试使用wget:

下载该文件
wget https://X.X.X.X:8443/path/2f6b88cf2b70ee933197edfc9627a9bc/ --no-check-certificate
--2015-09-07 14:36:12--  https://X.X.X.X:8443/path/2f6b88cf2b70ee933197edfc9627a9bc/
Connecting to X.X.X.X:8443... connected.
WARNING: The certificate of ‘X.X.X.X’ is not trusted.
WARNING: The certificate of ‘X.X.X.X’ hasn't got a known issuer.
The certificate's owner does not match hostname ‘X.X.X.X’
HTTP request sent, awaiting response... 302 Found
Location: https://X.X.X.X:8443/files/test.zip [following]
--2015-09-07 14:36:16--  https://X.X.X.X:8443/files/test.zip
Reusing existing connection to X.X.X.X:8443.
HTTP request sent, awaiting response... 200 OK
Length: 321917584 (307M) [application/zip]
Saving to: ‘test.zip’

test.zip                                  100%[====================================================================================>] 307.00M   253KB/s   in 19m 50ss

完成文件在20分钟后成功保存在磁盘上。

HttpURLConnection有什么问题?

编辑: 我尝试通过http协议从其他服务器下载测试文件,一切正常。它似乎是服务器或协议特定的问题。但为什么wget设法下载整个文件?

Edit2:按照你的建议我也尝试过:

  • 删除connection.setDoOutput(true);
  • 使用直接链接来避免重定向302
  • 通过自定义实现替换Files.copy方法

不幸的是,以上都没有帮助。

EDIT3: 我注意到该文件也可以通过不安全的http协议在同一台服务器上使用。所以我只更改了代码中的URL,并且在 120 秒之后我得到了:

Exception in thread "main" java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:196)
    at java.net.SocketInputStream.read(SocketInputStream.java:122)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:273)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
    at sun.net.www.MeteredStream.read(MeteredStream.java:134)
    at java.io.FilterInputStream.read(FilterInputStream.java:133)
    at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3066)
    at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3060)
    at java.nio.file.Files.copy(Files.java:2735)
    at java.nio.file.Files.copy(Files.java:2854) 

2 个答案:

答案 0 :(得分:2)

我终于在It is not possible to download large files at Jetty server找到了解决方案(再次感谢StackOverflow)。问题出在服务器端。

我们使用的Jetty 9.2有一个错误,它会在慢速连接(https://bugs.eclipse.org/bugs/show_bug.cgi?id=472621)上中断服务大文件。似乎并不总是抛出异常。

Wget和浏览器以某种方式能够完成下载,尽管转移或连接重置失败。不幸的是我的Java应用程序更敏感......

将捆绑的Jetty升级到上一个稳定版本9.3.3修复了下载的所有问题。

答案 1 :(得分:0)

connection.setRequestMethod("GET");

在这里,您打算进行HTTP GET。

connection.setDoOutput(true);

在此您将其更改为PUT。

Files.copy(connection.getInputStream(), new File("test.zip").toPath());

在这里,您无需编写任何内容即可获得输入流。服务器仍在等待您从未发送的POST数据,因此它永远不会发送响应,因此您需要超时。

丢失setDoOutput(true);行。