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.