![](/img/trans.png)
[英]Getting UnknownLengthHttpInputStream while getting InputStream from HttpURLConnection in android
[英]FileNotFoundException while getting the InputStream object from HttpURLConnection
我正在尝试使用 HttpURLConnection(用于在 java 中使用 cUrl)向 url 发送发布请求。 请求的内容是 xml,在终点,应用程序处理 xml 并将记录存储到数据库,然后以 xml 字符串的形式发回响应。 该应用程序在本地托管在 apache-tomcat 上。
当我从终端执行此代码时,一行会按预期添加到数据库中。 但是从连接中获取InputStream时抛出如下异常
java.io.FileNotFoundException: http://localhost:8080/myapp/service/generate
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1401)
at org.kodeplay.helloworld.HttpCurl.main(HttpCurl.java:30)
这是代码
public class HttpCurl {
public static void main(String [] args) {
HttpURLConnection con;
try {
con = (HttpURLConnection) new URL("http://localhost:8080/myapp/service/generate").openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setDoInput(true);
File xmlFile = new File("test.xml");
String xml = ReadWriteTextFile.getContents(xmlFile);
con.getOutputStream().write(xml.getBytes("UTF-8"));
InputStream response = con.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(response));
for (String line ; (line = reader.readLine()) != null;) {
System.out.println(line);
}
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
它令人困惑,因为异常被追踪到行InputStream response = con.getInputStream();
并且似乎没有任何文件涉及 FileNotFoundException。
当我尝试直接打开与 xml 文件的连接时,它不会抛出此异常。
服务应用程序使用 spring 框架和 Jaxb2Marshaller 来创建响应 xml。
ReadWriteTextFile 类取自此处
谢谢。
编辑:它会将数据保存在数据库中,同时发回 404 响应状态代码。
我还尝试使用 php 进行卷曲并打印出CURLINFO_HTTP_CODE
结果是 200。
关于如何调试这个的任何想法? 服务和客户端都在本地服务器上。
已解决:我可以在参考SO本身的答案后解决问题。
似乎 HttpURLConnection 在连接到具有非标准端口的 url 时总是返回 404 响应。
添加这些行解决了它
con.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
con.setRequestProperty("Accept","*/*");
我不知道你的 Spring/JAXB 组合,但一般的 REST web 服务不会在 POST/PUT 上返回响应主体,只是一个响应状态。 你想确定它而不是身体。
代替
InputStream response = con.getInputStream();
经过
int status = con.getResponseCode();
HTTP 规范中提供了所有可用的状态代码及其含义,如前所述。 Web 服务本身还应该附带一些文档,这些文档概述了 Web 服务支持的所有状态代码及其特殊含义(如果有的话)。
如果状态以4nn
或5nn
,您希望改用getErrorStream()
来读取可能包含错误详细信息的响应正文。
InputStream error = con.getErrorStream();
FileNotFound
只是一个不幸的异常,用于指示 Web 服务器返回 404。
对于将来遇到此问题的任何人,原因是状态代码是 404(或者在我的情况下是 500)。 当状态代码不是 200 时, InpuStream
函数似乎会抛出错误。
在我的例子中,我控制我自己的服务器并返回 500 状态代码以指示发生错误。 尽管我还发送了一个包含详细说明错误的字符串消息的正文,但无论正文是否完全可读,输入inputstream
都会抛出错误。
如果您控制服务器,我想这可以通过向自己发送 200 状态代码然后处理字符串错误响应来处理。
对于其他遇到此问题的人,在尝试将 SOAP 请求标头发送到 SOAP 服务时,同样的事情也发生在我身上。 问题是代码中的顺序错误,我在发送 XML 正文之前先请求了输入流。 在下面的代码中, InputStream in = conn.getInputStream();
行在ByteArrayOutputStream out = new ByteArrayOutputStream();
这是错误的顺序。
ByteArrayOutputStream out = new ByteArrayOutputStream();
// send SOAP request as part of HTTP body
byte[] data = request.getHttpBody().getBytes("UTF-8");
conn.getOutputStream().write(data);
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
Log.d(TAG, "http response code is " + conn.getResponseCode());
return null;
}
InputStream in = conn.getInputStream();
在这种情况下, FileNotFound
是一种不幸的编码 HTTP 响应代码 400 的方式。
在这种情况下,FileNotFound 意味着您从服务器收到了 404 - 可能是服务器不喜欢“POST”请求吗?
在这种情况下,FileNotFound 意味着您从服务器收到了 404
您必须设置请求内容类型标头参数 将“content-type”请求标头设置为“application/json”,以便以 JSON 形式发送请求内容。
必须设置此参数才能以 JSON 格式发送请求正文。
如果不这样做,服务器将返回 HTTP 状态代码“400-bad request”。
con.setRequestProperty("Content-Type", "application/json; utf-8");
完整脚本 ->
public class SendDeviceDetails extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
String data = "";
String url = "";
HttpURLConnection con = null;
try {
// From the above URL object,
// we can invoke the openConnection method to get the HttpURLConnection object.
// We can't instantiate HttpURLConnection directly, as it's an abstract class:
con = (HttpURLConnection)new URL(url).openConnection();
//To send a POST request, we'll have to set the request method property to POST:
con.setRequestMethod("POST");
// Set the Request Content-Type Header Parameter
// Set “content-type” request header to “application/json” to send the request content in JSON form.
// This parameter has to be set to send the request body in JSON format.
//Failing to do so, the server returns HTTP status code “400-bad request”.
con.setRequestProperty("Content-Type", "application/json; utf-8");
//Set Response Format Type
//Set the “Accept” request header to “application/json” to read the response in the desired format:
con.setRequestProperty("Accept", "application/json");
//To send request content, let's enable the URLConnection object's doOutput property to true.
//Otherwise, we'll not be able to write content to the connection output stream:
con.setDoOutput(true);
//JSON String need to be constructed for the specific resource.
//We may construct complex JSON using any third-party JSON libraries such as jackson or org.json
String jsonInputString = params[0];
try(OutputStream os = con.getOutputStream()){
byte[] input = jsonInputString.getBytes("utf-8");
os.write(input, 0, input.length);
}
int code = con.getResponseCode();
System.out.println(code);
//Get the input stream to read the response content.
// Remember to use try-with-resources to close the response stream automatically.
try(BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"))){
StringBuilder response = new StringBuilder();
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
System.out.println(response.toString());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (con != null) {
con.disconnect();
}
}
return data;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.e("TAG", result); // this is expecting a response code to be sent from your server upon receiving the POST data
}
并称之为
new SendDeviceDetails().execute("");
您可以在本教程中找到更多详细信息
解决方案:
只需将localhost更改为您 PC 的IP
如果你想知道这个: Windows+r > cmd > ipconfig
例子:http://192.168.0.107/directory/service/program.php?action= sendSomething
只需将192.168.0.107替换为您自己的 IP(不要尝试127.0.0.1因为它与localhost相同)
请更换
con = (HttpURLConnection) new URL("http://localhost:8080/myapp/service/generate").openConnection();
到
con = (HttpURLConnection) new URL("http://YOUR_IP:8080/myapp/service/generate").openConnection();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.