HttpURLConnection에서 InputStream 개체를 가져 오는 동안 FileNotFoundException이 발생했습니다.


109

HttpURLConnection을 사용하여 URL에 게시 요청을 보내려고합니다 (Java에서 cUrl 사용). 요청의 내용은 xml이고 끝점에서 응용 프로그램은 xml을 처리하고 데이터베이스에 레코드를 저장 한 다음 xml 문자열 형식으로 응답을 다시 보냅니다. 앱은 apache-tomcat에서 로컬로 호스팅됩니다.

터미널에서이 코드를 실행하면 예상대로 행이 db에 추가됩니다. 그러나 연결에서 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 파일에 대한 연결을 직접 열려고하면이 예외가 발생하지 않습니다.

서비스 앱은 스프링 프레임 워크와 Jaxb2Marshaller를 사용하여 응답 xml을 생성합니다.

ReadWriteTextFile 클래스는 여기 에서 가져옵니다 .

감사.

편집 : DB에 데이터를 저장하고 동시에 404 응답 상태 코드를 보냅니다.

나는 또한 PHP를 사용하여 컬을 시도하고 CURLINFO_HTTP_CODE200으로 판명 된 것을 인쇄했습니다 .

이것을 디버깅하는 방법에 대한 아이디어가 있습니까? 서비스와 클라이언트는 모두 로컬 서버에 있습니다.

해결 : SO 자체에 대한 답변 을 참조하여 문제를 해결할 수 있습니다.

표준 포트가 아닌 URL에 연결할 때 HttpURLConnection이 항상 404 응답을 반환하는 것 같습니다.

이 줄을 추가하면 해결되었습니다.

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

1
"터미널에서이 코드를 실행할 때"-어떤 코드입니까? 작동하는 것과 작동하지 않는 것이 명확하지 않습니다.
Jon Skeet

HttpCurl은이 기본 메서드가있는 클래스의 이름입니다. 이 클래스는 터미널에서 컴파일되고 실행됩니다
naiquevin 2011 년

3
동일한 문제가 발생했지만 여기에서 해결책이 작동하지 않았습니다. 결국 Java 1.7.0_05의 문제라는 것을 알았고 최신 버전 1.7.0_21로 업데이트하고 문제가 사라졌습니다. 또한 Java 1.6에서는 문제가 발생하지 않았 음을 깨달았습니다. 여전히 붙어있는 사람을위한 FYI.
스티븐

여러분! 답변보다는 질문에 대한 "해결됨"주석을 참조하십시오!
김준호

답변:


130

Spring / JAXB 조합에 대해서는 모르지만 평균 REST 웹 서비스는 POST / PUT에서 응답 본문을 반환하지 않고 응답 상태 만 반환합니다 . 신체 대신 결정하고 싶습니다.

바꾸다

InputStream response = con.getInputStream();

으로

int status = con.getResponseCode();

사용 가능한 모든 상태 코드와 의미는 이전에 링크 된대로 HTTP 사양에서 사용할 수 있습니다. 웹 서비스 자체는 웹 서비스에서 지원하는 모든 상태 코드와 해당하는 경우 그 특별한 의미를 개괄하는 문서와 함께 제공되어야합니다.

상태가 4nn또는로 시작하는 경우 오류 세부 정보를 포함 할 수있는 응답 본문을 읽는 데 대신 5nn사용할 getErrorStream()수 있습니다.

InputStream error = con.getErrorStream();

좋아, 나는 이것을 시도하고 상태 404를 반환합니다.하지만 이상하게도 DB에 저장됩니다! 또한 언급 한 내용에서 REST 서비스가 상태 코드 만 반환한다는 의미입니까? xml 유효성 검사 오류 메시지 또는 게시물이 성공한 경우 URL과 같은 추가 정보를 반환하려면 어떻게해야합니까?
naiquevin 2011 년

예, POST / PUT / etc와 같은 수정 요청에서 일반적으로 본문을 반환하지 않습니다. 일반적으로 입력 또는 오류 스트림을 읽기 전에 응답 상태를 확인하려고합니다. 나는 대답에 몇 가지 세부 사항을 추가했습니다. 그러나 실제로 상태 404를 반환하는 경우 웹 서비스에 버그가있을 수 있습니다. 나는 그것의 관리자에게보고 할 것이다.
BalusC 2011 년

이 경우 서비스 관리자는 나입니다! .. 나는 PHP를 사용하여 컬을 시도했고 200을 반환합니다 (제 질문을 편집했습니다) 또한 getErrorStream()제안대로 시도 했습니다. 에 NullPointerException이 발생합니다 new InputStreamReader(con.getErrorStream()).
naiquevin 2011 년

죄송합니다. 저는 Spring 웹 서비스에 익숙하지 않습니다. 저는 표준 Java EE 5/6 API에서 JAX-WS / RS에 대한 경험 만 가지고 있습니다. XML 파일 처리를 담당하는 메서드에 중단 점을 설정 한 다음 거기에서 한 단계 더 나아가는 것이 좋습니다.
BalusC 2011 년

이 동작은 특히 더 일반적인 URLConnection문제를 참조하기 때문에 매우 유용하지 않은 것 같습니다 . 자바 사람은 간단하게 구현하지 않았는지 궁금 getInputStream()에서 HttpUrlConnection의 라인을 따라 return responseCode == 200 ? super.getInputStream() : this.getErrorStream(). 그러나 어쨌든; 유익한 답변, +1.
aroth

51

FileNotFound 웹 서버가 404를 반환했음을 나타내는 데 사용되는 불행한 예외입니다.


1
이것은 OP에서 언급 한대로 행이 DB에 추가되는 이유를 설명하지 않습니다.
BalusC 2011 년

@BalusC : 서버가 행을 추가 한 다음 404 반환 하지 않는 한.
Jon Skeet

예, 이런 식으로 작동하는 것 같습니다. 무슨 뜻인가요 ?
naiquevin 2011 년

@naiquevin : 말하기는 어렵지만 로컬에서 실행되는 서비스이므로 직접 디버깅 할 수 있어야합니다.
Jon Skeet 2011 년

7
HttpURLConnection은 또한 403 응답 (및 기타)에 대해 FileNotFoundException을 발생시킵니다. (응답 본문이 비어 있지 않더라도 보인다.) 어쨌든를 getResponseCode()호출하기 전에 항상 조사하십시오 getInputStream().
Jonik

29

앞으로이 문제가있는 사람에게는 상태 코드가 404 (또는 제 경우에는 500)이기 때문입니다. InpuStream상태 코드가 200이 아닌 경우 함수에서 오류가 발생하는 것으로 보입니다 .

제 경우에는 자체 서버를 제어하고 오류가 발생했음을 나타내는 500 상태 코드를 반환했습니다. 오류를 자세히 설명하는 문자열 메시지와 함께 본문을 보냈음에도 불구하고 inputstream본문이 완전히 읽을 수 있는지에 관계없이 오류가 발생했습니다.

서버를 제어하는 ​​경우 200 상태 코드를 보낸 다음 문자열 오류 응답을 처리하여 처리 할 수 ​​있다고 가정합니다.


21
분명히 말하면, 당신은 그것을 잘못 취급하고 있습니다. 괜찮은지 확인하려면 connection.getResponseCode를 사용해야합니다. 그런 다음 connection.getErrorStream을 사용하여 getInputStream 대신 오류 본문을 가져옵니다. (또는 getResponseMessage를 사용할 수 있습니다) 오류 인 경우 200 상태 코드를 보내지 말고 의도 한대로 http 오류 코드를 사용하십시오.
rekh127 2014

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

FileNotFound 이 경우는 HTTP 응답 코드 400을 인코딩하는 불행한 방법이었습니다.


FileNotFound는 연결에 uput 스트림이 없기 때문입니다. 응답 코드 400 인코딩과는 아무런 관련이 없습니다. getResponseCode ()를 사용하여 응답 코드를 얻을 수 있습니다. 그런 다음 HTTP_OK가 아니면 conn.getErrorStream () 또는 getResponseMessage ()를 사용하여 본문을
가져와야합니다.

new ByteArrayOutputStream()그것과는 아무 관련이 없습니다. 문제는 사이 같은 순서입니다 getInputStream()getResponseCode().
Marquis of Lorne

4

이 경우 FileNotFound는 서버에서 404를 받았음을 의미합니다. 서버가 "POST"요청을 좋아하지 않을 수 있습니까?


그러나 레코드를 db에 저장합니다. Jaxb2Marshaller가 여기서 문제가 될 수 있습니까?
naiquevin 2011 년

2
이것은 404에서만 발생하는 것이 아닙니다. 본문이 비어있는 모든 응답에도 발생합니다.
Dave Cameron

3
이 대답은 불행히도 틀 렸습니다. 이 상황에서 FileNotFound는 응답 코드가 399 이상일 때 HttpURLConnection # getInputStream ()이 호출되었음을 의미하는 반면,이 상황에서는 HttpURLConnection # getErrorStream ()이 호출되어야합니다. OTOH, 서버가 POST를 수락하지 않으면 405 Method Not Allowed를 반환했을 것입니다. 거기에 던져지는 FileNotFound와 관련이 없습니다.
Michal M

0

해결책 : 이것을 알고 싶다면 PC 의 IP 에 대한 localhost
변경 하십시오 : Windows + r> cmd> ipconfig 예제 : http : // 192.168.0.107 /directory/service/program.php?action=sendSomething just replace 192.168 자신의 IP에 대해 .0.107 ( localhost 와 동일하므로 127.0.0.1을 시도하지 마십시오 )



-4

바꿔주세요

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

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

2
변경 하시겠습니까? OP는 서비스가 로컬에서 실행 중이라고 구체적으로 명시했습니다.
Marquis of Lorne

localhost에서 이미지 리소스를 가져와야하는 경우 작동하지 않습니다.
Phuoc Huynh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.