117

我正在尝试使用 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 进行 curl 并打印出CURLINFO_HTTP_CODE结果为 200。

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

已解决: 参考SO 本身的答案后,我可以解决问题。

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

添加这些行解决了它

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

8 回答 8

136

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

代替

InputStream response = con.getInputStream();

经过

int status = con.getResponseCode();

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

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

InputStream error = con.getErrorStream();
于 2011-03-21T14:54:06.533 回答
54

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

于 2011-03-21T14:47:01.460 回答
32

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

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

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

于 2014-05-25T17:09:37.547 回答
4

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

于 2011-03-21T14:45:15.260 回答
4

对于其他对此感到困惑的人,我在尝试将 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 是一种不幸的方式。

于 2014-03-10T15:24:50.633 回答
0

在这种情况下,FileNotFound 意味着您从服务器获得了 404

您必须设置请求 Content-Type 标头参数 将“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

于 2021-01-20T21:43:28.733 回答
-1

解决方案: 如果您想知道,
只需更改PC 的IP的localhost : 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相同)


于 2016-08-13T19:29:31.440 回答
-5

请更换

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

con = (HttpURLConnection) new URL("http://YOUR_IP:8080/myapp/service/generate").openConnection();
于 2016-01-29T09:32:48.173 回答