2012-11-21 23 views
1

如果文件是特定內容類型,我正嘗試從URL下載文件。該URL可以提供html或pdf頁面,我只想保存pdf文件。我在做此嘗試以下:如何在確認內容類型後將URL保存到文件中?

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的調用將成功,而不會重置連接。我是否會引入某種總是失敗的競爭條件?

+0

你獲取內容類型之後就重新連接或connection.setReadTimeOut –

+1

我認爲[主治]玩(http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4)不應該返回你的文件的內容。 – ShyJ

+0

對'copyURLToFile'的調用會創建一個新連接,所以它不應該使用HEAD請求從URL獲取輸入流。 –

回答

2

你應該用開放連接讀取數據:

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

無需打開另一個連接,可能是服務器重置連接?

編輯:沒有的請求方法的設置,但有一個得到這個工作對我來說:

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(); 
+0

我也試過,但我不確定是否必須在發出HEAD請求後以某種方式重置連接。此調用不會導致異常,但URL的內容不會保存到文件中。一個空文件被創建。我嘗試通過connection.setRequestMethod(「GET」)將請求方法改回GET,但仍然沒有運氣。 –

+0

對不起,在原始代碼中沒有看到HEAD請求方法。但有了GET(請參閱編輯答案),它適用於我。所有這些聽起來像是由服務器完成的連接重置,而不是代碼的問題。 –

+0

是的,如果我使用GET請求,它可以工作。我只是試圖讓HEAD請求工作,以便在確認它是我想保存的內容類型之前,我沒有獲取文件的內容。感謝您的回答!我可能會放棄讓HEAD請求工作,只是浪費帶寬... :) –

2

爲什麼不在讀完頭部後關閉連接?

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

FileUtils應該打開一個新的連接,並且您的問題可能會得到解決。

+0

我曾嘗試在調用getContentType()後添加'connection.disconnect()',但我仍然以相同的異常結束。 –

相關問題