从HttpURLConnection获取InputStream对象时出现FileNotFoundException

nai*_*vin 96 java inputstream filenotfoundexception httpurlconnection

我正在尝试使用HttpURLConnection向网址发送帖子请求(在java中使用cUrl).请求的内容是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)
Run Code Online (Sandbox Code Playgroud)

这是代码

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();
        }
    }
  }
Run Code Online (Sandbox Code Playgroud)

它令人困惑,因为异常被追溯到该行,InputStream response = con.getInputStream();并且似乎没有涉及FileNotFoundException的任何文件.

当我尝试直接打开与xml文件的连接时,它不会抛出此异常.

服务应用程序使用spring框架和Jaxb2Marshaller来创建响应xml.

ReadWriteTextFile类取自此处

谢谢.

编辑: 它将数据保存在数据库中,并同时发回404响应状态代码.

我也尝试使用php进行卷曲并打印出CURLINFO_HTTP_CODE结果为200.

关于如何进行调试的任何想法?服务和客户端都在本地服务器上.

已解决: 在提到SO本身的答案后,我可以解决问题.

当连接到具有非标准端口的URL时,似乎HttpURLConnection始终返回404响应.

添加这些线解决了它

con.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
con.setRequestProperty("Accept","*/*");
Run Code Online (Sandbox Code Playgroud)

Bal*_*usC 124

我不知道您的Spring/JAXB组合,但普通的REST Web服务不会在POST/PUT上返回响应主体,只是响应状态.你想确定它而不是身体.

更换

InputStream response = con.getInputStream();
Run Code Online (Sandbox Code Playgroud)

通过

int status = con.getResponseCode();
Run Code Online (Sandbox Code Playgroud)

所有可用的状态代码及其含义都在HTTP规范中提供,如之前链接的那样.Web服务本身也应该附带一些文档,这些文档概述了Web服务支持的所有状态代码及其特殊含义(如果有的话).

如果状态以4nn或开头5nn,则您希望使用它getErrorStream()来读取可能包含错误详细信息的响应正文.

InputStream error = con.getErrorStream();
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 48

FileNotFound 只是一个不幸的例外,用于表示Web服务器返回404.

  • HttpURLConnection还会为403响应(可能还有其他响应)抛出FileNotFoundException.(即使响应体不是*空的,似乎也是.)无论如何,在调用`getInputStream()`之前总是调查`getResponseCode()`. (6认同)
  • 这并不能解释为什么如 OP 所述将行添加到数据库中。 (3认同)

Ter*_*how 28

对于将来遇到此问题的任何人,原因是因为状态代码是404(或者在我的情况下是500).InpuStream当状态代码不是200时,该函数似乎会抛出错误.

在我的情况下,我控制自己的服务器,并返回500状态代码,以指示发生错误.尽管我还发送了一个带有详细信息错误的字符串消息的正文,但inputstream无论正文是否完全可读,都会抛出错误.

如果你控制你的服务器,我想这可以通过发送一个200状态代码然后处理字符串错误响应的任何处理来处理.

  • 要清楚,你只是处理它错了.您应该使用connection.getResponseCode来检查它是否正常.然后使用connection.getErrorStream来获取错误体而不是getInputStream.(或者您可以使用getResponseMessage)如果是错误,则不应发送200状态代码,请按预期使用http错误代码. (20认同)

zer*_*ool 5

对于任何绊倒这个的人来说,在尝试将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();
Run Code Online (Sandbox Code Playgroud)

FileNotFound 在这种情况下,编码HTTP响应代码400是一种不幸的方式.


tof*_*arr 4

在这种情况下,FileNotFound 意味着您从服务器收到 404 - 可能是服务器不喜欢“POST”请求?

  • 不幸的是,这个答案是错误的。这种情况下的 FileNotFound 仅意味着当响应代码高于 399 时才调用 HttpURLConnection#getInputStream(),而在这种情况下应该调用 HttpURLConnection#getErrorStream()。OTOH,如果服务器不接受 POST,它会返回 405 Method Not allowed。与在那里抛出 FileNotFound 无关。 (3认同)
  • 这不仅仅发生在 404 中。对于任何空体响应也会发生这种情况。 (2认同)