在Java中,当HTTP结果为404范围时,此代码抛出异常:
URL url = new URL("http://stackoverflow.com/asdf404notfound");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.getInputStream(); // throws!
在我的情况下,我碰巧知道内容是404,但我仍然想阅读回复的正文。
(在我的实际案例中,响应代码是403,但是响应正文解释了拒绝的原因,我想将其显示给用户。)
如何访问响应正文?
答案 0 :(得分:152)
Here is the bug report(关闭,不会修复,不是错误)。
他们的建议就是编码:
HttpURLConnection httpConn = (HttpURLConnection)_urlConnection;
InputStream _is;
if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
_is = httpConn.getInputStream();
} else {
/* error from server */
_is = httpConn.getErrorStream();
}
答案 1 :(得分:13)
这与我遇到的问题相同:
如果您尝试从连接中读取HttpUrlConnection
,则FileNotFoundException
会返回getInputStream()
当状态代码高于400时,您应该使用getErrorStream()
。
除此之外,请注意,因为成功状态代码不仅仅是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....
通过这种方式,您将能够在成功和错误情况下获得所需的响应。
希望这有帮助!
答案 2 :(得分:10)
在.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();
}
答案 3 :(得分:2)
我知道这不能直接回答这个问题,但是你可能想看看Commons HttpClient,而不是使用Sun提供的HTTP连接库,这在我看来很远更容易使用的API。
答案 4 :(得分:2)
首先检查响应代码,然后使用HttpURLConnection.getErrorStream()
答案 5 :(得分:0)
InputStream is = null;
if (httpConn.getResponseCode() !=200) {
is = httpConn.getErrorStream();
} else {
/* error from server */
is = httpConn.getInputStream();
}
答案 6 :(得分:0)
我的运行代码。
HttpURLConnection httpConn = (HttpURLConnection) urlConn;
if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
in = new InputStreamReader(urlConn.getInputStream());
BufferedReader bufferedReader = new BufferedReader(in);
if (bufferedReader != null) {
int cp;
while ((cp = bufferedReader.read()) != -1) {
sb.append((char) cp);
}
bufferedReader.close();
}
in.close();
} else {
/* error from server */
in = new InputStreamReader(httpConn.getErrorStream());
BufferedReader bufferedReader = new BufferedReader(in);
if (bufferedReader != null) {
int cp;
while ((cp = bufferedReader.read()) != -1) {
sb.append((char) cp);
}
bufferedReader.close();
}
in.close();
}
System.out.println("sb="+sb);
答案 7 :(得分:0)
如何在Java中读取404响应正文:
使用Apache库-https://hc.apache.org/httpcomponents-client-4.5.x/httpclient/apidocs/
或 Java 11-https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html
下面给出的代码片段使用Apache:
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
CloseableHttpClient client = HttpClients.createDefault();
CloseableHttpResponse resp = client.execute(new HttpGet(domainName + "/blablablabla.html"));
String response = EntityUtils.toString(resp.getEntity());