2009-03-05 37 views
63

在Java中,這個代碼拋出一個異常時,HTTP結果爲404範圍:讀取錯誤響應主體在Java中

URL url = new URL("http://stackoverflow.com/asdf404notfound"); 
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
conn.getInputStream(); // throws! 

就我而言,我碰巧知道內容是404,但我仍然喜歡閱讀反應的正文。

(在我的實際情況下的響應代碼是403,但響應的身體解釋了拒絕的原因,我想顯示給用戶。)

如何訪問響應身體?

+0

您確定服務器正在發送正文嗎? – 2009-03-05 01:50:40

+0

什麼是例外? – jdigital 2009-03-05 02:05:25

+2

@jdigital:HttpURLConnection.getInputStream()引發的異常是java.io.FileNotFoundException。 (主要提到這個更好的googlability。) – Jonik 2014-01-29 16:34:10

回答

127

Here is the bug report(接近,不會修復,而不是bug)。

他們的建議有像這樣的代碼:如果您嘗試讀取的連接getInputStream() HttpUrlConnection回報FileNotFoundException

HttpURLConnection httpConn = (HttpURLConnection)_urlConnection; 
InputStream _is; 
if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) { 
    _is = httpConn.getInputStream(); 
} else { 
    /* error from server */ 
    _is = httpConn.getErrorStream(); 
} 
2

我知道這並不是直接回答問題,而是使用Sun提供的HTTP連接庫,您可能想看看Commons HttpClient,這在我看來具有更簡單的API,與...合作。

+4

我不同意。只要你做了非常簡單的事情,來自Sun的API就容易得多。通過簡單的東西,我的意思是一個GET沒有太多的錯誤處理,這對於大量的情況已經足夠了。當然,HttpClient在功能上遠遠優越。 – 2011-05-31 09:47:13

+0

截至2014年,最好的可能是[OkHttp](http://square.github.io/okhttp/)(實際上在打開URL時返回HttpURLConnection實例)。特別是在Android上,它可以幫助您避免純HttpURLConnection和Apache HttpClient的一些令人討厭的問題。 – Jonik 2014-01-29 16:41:27

2

首先檢查響應代碼,然後使用HttpURLConnection.getErrorStream()

0
InputStream is = null; 
if (httpConn.getResponseCode() !=200) { 
    is = httpConn.getErrorStream(); 
} else { 
    /* error from server */ 
    is = httpConn.getInputStream(); 
} 
10

這是我有同樣的問題。
您應該改用getErrorStream()當狀態代碼爲高於400

比這更多,請小心,因爲它不僅是200是成功狀態碼,甚至201,204,等經常被用來作爲成功狀態。

下面是我如何去管理它

... connection code code code ... 

// Get the response code 
int statusCode = connection.getResponseCode(); 

InputStream is = null; 

if (statusCode >= 200 && statusCode < 400) { 
    // Create an InputStream in order to extract the response object 
    is = connection.getInputStream(); 
} 
else { 
    is = connection.getErrorStream(); 
} 

... callback/response to your handler.... 

這樣一個例子,你將能夠獲得成功和錯誤的情況下所需要的響應。

希望這有助於!

6

在.Net中,您擁有WebException的Response屬性,該屬性允許訪問流上的異常。所以我想這是一個Java的好方法,...

private InputStream dispatch(HttpURLConnection http) throws Exception { 
    try { 
     return http.getInputStream(); 
    } catch(Exception ex) { 
     return http.getErrorStream(); 
    } 
} 

或我使用的實現。 (可能需要更改編碼或其他東西,適用於當前環境)

private String dispatch(HttpURLConnection http) throws Exception { 
    try { 
     return readStream(http.getInputStream()); 
    } catch(Exception ex) { 
     readAndThrowError(http); 
     return null; // <- never gets here, previous statement throws an error 
    } 
} 

private void readAndThrowError(HttpURLConnection http) throws Exception { 
    if (http.getContentLengthLong() > 0 && http.getContentType().contains("application/json")) { 
     String json = this.readStream(http.getErrorStream()); 
     Object oson = this.mapper.readValue(json, Object.class); 
     json = this.mapper.writer().withDefaultPrettyPrinter().writeValueAsString(oson); 
     throw new IllegalStateException(http.getResponseCode() + " " + http.getResponseMessage() + "\n" + json); 
    } else { 
     throw new IllegalStateException(http.getResponseCode() + " " + http.getResponseMessage()); 
    } 
} 

private String readStream(InputStream stream) throws Exception { 
    StringBuilder builder = new StringBuilder(); 
    try (BufferedReader in = new BufferedReader(new InputStreamReader(stream))) { 
     String line; 
     while ((line = in.readLine()) != null) { 
      builder.append(line); // + "\r\n"(no need, json has no line breaks!) 
     } 
     in.close(); 
    } 
    System.out.println("JSON: " + builder.toString()); 
    return builder.toString(); 
}