1

如果文件是特定内容类型,我正在尝试从 URL 下载文件。该 URL 可以提供 html 或 pdf 页面,我只想保存 pdf 文件。我这样做的尝试如下:

HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
connection.connect();
String contentType = connection.getContentType();

if (contentType.equals("application/pdf")) {
      org.apache.commons.io.FileUtils.copyURLToFile(url, file);
}

contentType 被正确获取,但调用copyURLToFile(url,file);导致以下异常:

java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(Unknown Source)
at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(Unknown Source)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read1(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at java.io.FilterInputStream.read(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Unknown Source)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1025)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:999)
at org.apache.commons.io.FileUtils.copyURLToFile(FileUtils.java:848)

如果我删除用于获取 contentType 的代码行,并且只调用copyURLToFile(url,file),则文件已成功下载并保存。我是否HttpURLConnection以某种方式处理不当导致我的连接被重置?

我还注意到,如果我在该if(contentType.equals("application/pdf")行上设置断点并等待几秒钟,则调用copyURLToFile成功而连接不会被重置。我是否引入了某种总是失败的竞争条件?

4

2 回答 2

2

为什么不尝试在阅读 HEAD 后关闭连接?

   HttpURLConnection connection = (HttpURLConnection) url.openConnection();
   connection.setRequestMethod("HEAD");
   connection.connect();
   String contentType = connection.getContentType();
   connection.close();

然后 FileUtils 应该打开一个新连接,您的问题可能会得到解决。

于 2012-11-21T13:48:06.690 回答
2

您应该使用打开的连接来读取数据:

org.apache.commons.io.IOUtils.copy(connection.getInputStream(), new FileOutputStream(file));

不需要打开另一个连接,可能是服务器重置了连接?

编辑:没有请求方法设置,但是使用 GET 这对我有用:

public static void main(String args[]) throws IOException{
    URL url = new URL("http://www.google.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("GET");
    String contentType = connection.getContentType();
    System.out.println("content-type: " + contentType);
    IOUtils.copy(connection.getInputStream(), new FileOutputStream("/temp/test.html"));
}

编辑:或者那样,如果您想先检查带有 HEAD 请求的标头:

URL url = new URL("http://www.google.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
String contentType = connection.getContentType();
System.out.println("content-type: " + contentType);
connection.disconnect();
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
IOUtils.copy(connection.getInputStream(), new FileOutputStream("/temp/test.html"));
connection.disconnect();
于 2012-11-21T13:53:12.960 回答