从 HttpURLConnection 获取 InputStream 对象时出现 FileNotFoundException

发布于 2024-10-24 00:17:49 字数 2523 浏览 3 评论 0 原文

我正在尝试使用 HttpURLConnection (用于在 java 中使用 cUrl)向 url 发送 post 请求。 请求的内容是 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 本身而言。

当使用非标准端口连接到 url 时,HttpURLConnection 似乎总是返回 404 响应。

添加这些行解决了它

con.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
con.setRequestProperty("Accept","*/*");

I am trying to send a post request to a url using HttpURLConnection (for using cUrl in java).
The content of the request is xml and at the end point, the application processes the xml and stores a record to the database and then sends back a response in form of xml string. The app is hosted on apache-tomcat locally.

When I execute this code from the terminal, a row gets added to the db as expected. But an exception is thrown as follows while getting the InputStream from the connection

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)

Here is the code

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();
        }
    }
  }

Its confusing because the exception is traced to the line InputStream response = con.getInputStream(); and there doesn't seem to be any file involved for a FileNotFoundException.

When I try to open a connection to an xml file directly, it doesn't throw this exception.

The service app uses spring framework and Jaxb2Marshaller to create the response xml.

The class ReadWriteTextFile is taken from here

Thanks.

Edit:
Well it saves the data in the DB and sends back a 404 response status code at the same time.

I also tried doing a curl using php and print out the CURLINFO_HTTP_CODE which turns out to be 200.

Any ideas on how do I go about debugging this ? Both service and client are on the local server.

Resolved:
I could solve the problem after referring to an answer on SO itself.

It seems HttpURLConnection always returns 404 response when connecting to a url with a non standard port.

Adding these lines solved it

con.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
con.setRequestProperty("Accept","*/*");

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

水染的天色ゝ 2024-10-31 00:17:49

我不知道你的 Spring/JAXB 组合,但一般的 REST Web 服务不会在 POST/PUT 上返回响应正文,只是一个 响应状态。你想确定它而不是身体。

替换

InputStream response = con.getInputStream();

int status = con.getResponseCode();

HTTP 规范中提供了所有可用的状态代码及其含义,如前面链接的。 Web 服务本身还应该附带一些文档,概述 Web 服务支持的所有状态代码及其特殊含义(如果有)。

如果状态以 4nn5nn 开头,您需要使用 getErrorStream() 来读取可能包含错误的响应正文细节。

InputStream error = con.getErrorStream();

I don't know about your Spring/JAXB combination, but the average REST webservice won't return a response body on POST/PUT, just a response status. You'd like to determine it instead of the body.

Replace

InputStream response = con.getInputStream();

by

int status = con.getResponseCode();

All available status codes and their meaning are available in the HTTP spec, as linked before. The webservice itself should also come along with some documentation which overviews all status codes supported by the webservice and their special meaning, if any.

If the status starts with 4nn or 5nn, you'd like to use getErrorStream() instead to read the response body which may contain the error details.

InputStream error = con.getErrorStream();
等风来 2024-10-31 00:17:49

FileNotFound 只是一个不幸的异常,用于指示 Web 服务器返回了 404。

FileNotFound is just an unfortunate exception used to indicate that the web server returned a 404.

女皇必胜 2024-10-31 00:17:49

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

在我的例子中,我控制自己的服务器并返回 500 状态代码以指示发生了错误。尽管我还发送了带有详细说明错误的字符串消息的正文,但无论正文完全可读,inputstream 都会抛出错误。

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

To anyone with this problem in the future, the reason is because the status code was a 404 (or in my case was a 500). It appears the InpuStream function will throw an error when the status code is not 200.

In my case I control my own server and was returning a 500 status code to indicate an error occurred. Despite me also sending a body with a string message detailing the error, the inputstream threw an error regardless of the body being completely readable.

If you control your server I suppose this can be handled by sending yourself a 200 status code and then handling whatever the string error response was.

·深蓝 2024-10-31 00:17:49

对于其他遇到此问题的人来说,在尝试将 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 编码方式。

For anybody else stumbling over this, the same happened to me while trying to send a SOAP request header to a SOAP service. The issue was a wrong order in the code, I requested the input stream first before sending the XML body. In the code snipped below, the line InputStream in = conn.getInputStream(); came immediately after ByteArrayOutputStream out = new ByteArrayOutputStream(); which is the incorrect order of things.

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 in this case was an unfortunate way to encode HTTP response code 400.

初心 2024-10-31 00:17:49

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

FileNotFound in this case means you got a 404 from your server - could it be that the server does not like "POST" requests?

捎一片雪花 2024-10-31 00:17:49

在这种情况下,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("");

您可以在本教程中找到更多详细信息

https://www.baeldung.com/httpurlconnection-post

FileNotFound in this case means you got a 404 from your server

You Have to 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");

Full Script ->

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
}

and call it

new SendDeviceDetails().execute("");

you can find more details in this tutorial

https://www.baeldung.com/httpurlconnection-post

浅浅淡淡 2024-10-31 00:17:49

解决方案:

只需将 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 相同)

The solution:

just change localhost for the IP of your PC

if you want to know this: Windows+r > cmd > ipconfig

example: http://192.168.0.107/directory/service/program.php?action=sendSomething

just replace 192.168.0.107 for your own IP (don't try 127.0.0.1 because it's same as localhost)

寄离 2024-10-31 00:17:49

请更改

con = (HttpURLConnection) new URL("http://localhost:8080/myapp/service/generate").openConnection();

con = (HttpURLConnection) new URL("http://YOUR_IP:8080/myapp/service/generate").openConnection();

Please change

con = (HttpURLConnection) new URL("http://localhost:8080/myapp/service/generate").openConnection();

To

con = (HttpURLConnection) new URL("http://YOUR_IP:8080/myapp/service/generate").openConnection();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文