FileNotFoundException HttpURLConnection से InputStream ऑब्जेक्ट प्राप्त करते समय


109

मैं HttpURLConnection (जावा में cUrl का उपयोग करने के लिए) का उपयोग करके एक url के लिए पोस्ट अनुरोध भेजने की कोशिश कर रहा हूं। अनुरोध की सामग्री xml है और अंतिम बिंदु पर, अनुप्रयोग xml को संसाधित करता है और डेटाबेस के लिए एक रिकॉर्ड संग्रहीत करता है और फिर xml स्ट्रिंग के रूप में प्रतिक्रिया भेजता है। ऐप को स्थानीय स्तर पर एपाचे-टॉमकैट पर होस्ट किया गया है।

जब मैं टर्मिनल से इस कोड को निष्पादित करता हूं, तो एक पंक्ति अपेक्षित रूप से db में जुड़ जाती है। लेकिन कनेक्शन से इनपुटस्ट्रीम प्राप्त करते समय एक अपवाद निम्नानुसार फेंका गया है

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 फ़ाइल से कनेक्शन खोलने का प्रयास करता हूं, तो वह इस अपवाद को नहीं फेंकती।

सर्विस ऐप प्रतिक्रिया xml बनाने के लिए स्प्रिंग फ्रेमवर्क और जैक्सब 2 मार्शलर का उपयोग करता है।

कक्षा ReadWriteTextFile को यहाँ से लिया गया है

धन्यवाद।

संपादित करें: खैर यह DB में डेटा को बचाता है और एक ही समय में 404 प्रतिक्रिया स्थिति कोड वापस भेजता है।

मैंने भी php का उपयोग करके एक कर्ल करने की कोशिश की और प्रिंट आउट किया CURLINFO_HTTP_CODEजो 200 निकला।

इस बारे में कोई विचार कि मैं इसे डिबगिंग के बारे में कैसे बताता हूं? सेवा और ग्राहक दोनों स्थानीय सर्वर पर हैं।

हल: मैं SO पर ही जवाब देने के बाद समस्या का समाधान कर सकता था।

ऐसा लगता है कि HttpURLConnection हमेशा एक गैर मानक पोर्ट के साथ url से कनेक्ट होने पर 404 प्रतिक्रिया देता है।

इन पंक्तियों को जोड़कर इसे हल किया

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

1
"जब मैं टर्मिनल से इस कोड को निष्पादित करता हूं" - कौन सा कोड? यह स्पष्ट नहीं है कि क्या काम कर रहा है बनाम क्या काम नहीं कर रहा है।
जॉन स्कीट

HttpCurl उस क्लास का नाम है जिसमें यह मुख्य विधि है। इस वर्ग को संकलित किया जाता है और इसे टर्मिनल
नाइकेविन

3
मैंने एक ही मुद्दे का अनुभव किया, लेकिन यहां कोई भी समाधान काम नहीं किया। मुझे अंततः समझ में आया कि यह जावा 1.7.0_05 के साथ एक समस्या थी और नवीनतम संस्करण 1.7.0_21 को अद्यतन किया गया और समस्या दूर हो गई। मुझे यह भी एहसास हुआ कि जावा 1.6 में समस्या नहीं थी। अभी भी किसी के लिए एक FYI करना अटका हुआ है।
स्टीवन

दोस्तों! जवाब के बजाय सवाल पर "हल" टिप्पणी देखें!
김준호

जवाबों:


130

मुझे आपके स्प्रिंग / JAXB संयोजन के बारे में नहीं पता है, लेकिन औसत रिस्ट वेब्स सर्विस POST / PUT पर एक प्रतिक्रिया निकाय नहीं लौटाएगी, केवल एक प्रतिक्रिया स्थिति । आप इसे शरीर के बजाय निर्धारित करना चाहेंगे।

बदलने के

InputStream response = con.getInputStream();

द्वारा

int status = con.getResponseCode();

सभी उपलब्ध स्थिति कोड और उनके अर्थ HTTP कल्पना में उपलब्ध हैं, जैसा कि पहले लिंक किया गया था। Webservice को भी कुछ प्रलेखन के साथ आना चाहिए जो कि webservice द्वारा समर्थित सभी स्टेटस कोड और उनके विशेष अर्थ, यदि कोई हो, का साक्षात्कार करता है।

यदि स्थिति शुरू होती है 4nnया 5nn, आप getErrorStream()प्रतिक्रिया निकाय को पढ़ने के लिए उपयोग करना चाहते हैं जिसमें त्रुटि विवरण हो सकता है।

InputStream error = con.getErrorStream();

ठीक है, मैंने यह कोशिश की और यह स्थिति 404 देता है। लेकिन अजीब बात है, यह डीबी में भी बचत कर रहा है! यह भी कि आप क्या उल्लेख करते हैं, इसका मतलब यह है कि कोई भी REST सेवा केवल एक स्थिति कोड लौटाएगी? क्या होगा अगर मैं पोस्ट को सफल होने पर अधिक जानकारी जैसे कि एक xml सत्यापन त्रुटि संदेश या एक यूआरएल वापस करना चाहता हूं?
नाइकेविन

हां, POST / PUT / etc जैसे संशोधन अनुरोधों पर यह आमतौर पर एक निकाय नहीं लौटाएगा। आप आमतौर पर इनपुट या त्रुटि स्ट्रीम पढ़ने से पहले प्रतिक्रिया की स्थिति निर्धारित करना चाहेंगे। मैंने जवाब में कुछ विवरण जोड़ा। लेकिन अगर यह वास्तव में 404 की स्थिति में लौट रहा है, तो संभवतः वेबबस में कुछ बग है। मैं इसके रखवाले को रिपोर्ट करता हूँ।
बालुसक

इस मामले में सेवा का अनुरक्षण मेरे लिए होता है! .. वैसे मैंने php का उपयोग करके एक कर्ल करने की कोशिश की है और यह 200 रिटर्न करता है (मेरे सवाल को संपादित किया है) भी getErrorStream()सुझाए गए अनुसार। यह एक NullPointerException को फेंकता है new InputStreamReader(con.getErrorStream())
नाइकेविन

क्षमा करें, मैं स्प्रिंग webservices के साथ पारिवारिक नहीं हूं। मैंने केवल JAX-WS / RS को मानक Java EE 5/6 API से अनुभव किया है। मैं XML फ़ाइल को संसाधित करने के लिए जिम्मेदार विधि पर एक ब्रेकपॉइंट लगाने का सुझाव देता हूं और फिर वहां से आगे कदम बढ़ाता हूं।
बालुसक

यह व्यवहार बहुत गैर-उपयोगी लगता है, खासकर जब से यह अधिक सामान्य URLConnectionसमस्याग्रस्त द्वारा चीजों का संदर्भ देता है। मुझे आश्चर्य है कि क्यों जावा लोग बस को लागू नहीं किया था getInputStream()में HttpUrlConnectionकी तर्ज पर return responseCode == 200 ? super.getInputStream() : this.getErrorStream()। लेकिन किसी भी तरह; जानकारीपूर्ण उत्तर, +1।
एरोथ

51

FileNotFound केवल एक दुर्भाग्यपूर्ण अपवाद है जो यह इंगित करने के लिए उपयोग किया जाता है कि वेब सर्वर ने 404 लौटाया है।


1
यह व्याख्या नहीं करता है कि ओपी द्वारा बताई गई पंक्ति को DB में क्यों जोड़ा जाता है।
बालुसक

@BalusC: जब तक सर्वर एक पंक्ति जोड़ रहा है और फिर एक 404 वापस कर रहा है।
जॉन स्केट

हाँ यह इस तरह से व्यवहार करने लगता है। इसका क्या मतलब है ?
नाइकेविन

@naiquevin: यह कहना मुश्किल है, लेकिन यह देखते हुए कि यह स्थानीय स्तर पर चलने वाली सेवा है, आपको इसे स्वयं डिबग करने में सक्षम होना चाहिए।
जॉन स्कीट

7
HttpURLConnection भी 403 प्रतिक्रियाओं (और शायद अन्य) के लिए FileNotFoundException फेंकता है। (भले ही प्रतिक्रिया शरीर खाली हो, ऐसा लगता है।) वैसे भी, getResponseCode()कॉल करने से पहले हमेशा जांच करें getInputStream()
जोनिक

29

भविष्य में इस समस्या वाले किसी के लिए, इसका कारण यह है कि स्थिति कोड 404 था (या मेरे मामले में 500 था)। ऐसा प्रतीत होता है कि InpuStreamफ़ंक्शन 200 त्रुटि करेगा जब स्थिति कोड 200 नहीं होगा।

मेरे मामले में मैं अपने स्वयं के सर्वर को नियंत्रित करता हूं और त्रुटि होने का संकेत देने के लिए 500 स्थिति कोड लौटा रहा था। मेरे द्वारा त्रुटि संदेश का विवरण देने के inputstreamबावजूद भी, शरीर को पूरी तरह से पठनीय होने के बावजूद त्रुटि को फेंक दिया।

यदि आप अपने सर्वर को नियंत्रित करते हैं तो मुझे लगता है कि यह स्वयं को 200 स्टेटस कोड भेजकर और फिर जो भी स्ट्रिंग त्रुटि प्रतिक्रिया थी, उसे संभालकर नियंत्रित किया जा सकता है।


21
स्पष्ट होने के लिए, आप इसे गलत तरीके से संभाल रहे हैं। यह ठीक है या नहीं, यह जांचने के लिए आपको connection.getResponseCode का उपयोग करना चाहिए। फिर getInputStream के बजाय त्रुटि निकाय प्राप्त करने के लिए connection.getErrorStream का उपयोग करें। (या आप getResponseMessage का उपयोग कर सकते हैं) यदि आप एक त्रुटि होने पर 200 स्टेटस कोड नहीं भेजना चाहते हैं, तो इसका उपयोग http एरर कोड के लिए करें।
15:12 बजे re12127

5

इस पर ठोकर खाने वाले किसी अन्य व्यक्ति के लिए, SOAP सेवा को SOAP अनुरोध शीर्षलेख भेजने का प्रयास करते समय मेरे साथ भी ऐसा ही हुआ। समस्या कोड में एक गलत आदेश था, मैंने एक्सएमएल निकाय भेजने से पहले सबसे पहले इनपुट स्ट्रीम का अनुरोध किया। नीचे दिए गए कोड में, लाइन 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 था क्योंकि कनेक्शन में एक अप स्ट्रीम नहीं है। यह एन्कोडिंग प्रतिक्रिया कोड 400 के साथ कुछ नहीं करना था। आप getResponseCode () के साथ जिम्मेदारी ले सकते हैं। अगर यह HTTP_OK नहीं है तो आपको con.getErrorStream () या
getResponseMessage

new ByteArrayOutputStream()इसका इससे कोई लेना-देना नहीं है। इस मुद्दे के बीच getInputStream()और के रूप में आदेश है getResponseCode()
लोरेन का

4

इस मामले में FileNotFound का मतलब है कि आपको अपने सर्वर से 404 मिला है - क्या ऐसा हो सकता है कि सर्वर "POST" अनुरोधों को पसंद नहीं करता है?


लेकिन यह db के लिए एक रिकॉर्ड बचाता है। क्या यहां जैक्सबी 2 मार्शेलर समस्या हो सकती है?
नैक्विविन

2
यह केवल 404 के लिए नहीं होता है। यह खाली शरीर के साथ किसी भी प्रतिक्रिया के लिए भी होता है।
डेव कैमरून

3
यह जवाब, दुर्भाग्य से, गलत है। इस स्थिति में FileNotFound का मतलब केवल यह था कि प्रतिक्रिया कोड 399 से ऊपर होने पर HttpURLConnection # getInputStream () कहा जाता था, जबकि इस स्थिति में HttpURLConnection # getErrorStream () को कॉल किया जाना चाहिए था। OTOH, यदि सर्वर POST को स्वीकार नहीं करेगा, तो यह 405 मेथड Not Not Allowed वापस आ जाएगा। FileNotFound से कोई संबंध नहीं है।
मिशाल एम।

0

समाधान: यदि आप यह जानना चाहते हैं तो अपने पीसी के आईपी के लिए लोकलहोस्ट को
बदल दें : विंडोज + आर> सीएमडी> आईपीकॉन्फिग उदाहरण: http: // 192.168.0.107 /directory/service/program.php?action-sendSomething सिर्फ 192.168 बदलें अपने स्वयं के आईपी के लिए .0.107 ( 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
इसे बदलें क्यों? ओपी ने विशेष रूप से कहा है कि सेवा स्थानीय रूप से चल रही है।
लोर्ने

अगर u लोकलहोस्ट से इमेज रिसोर्स की जरूरत है तो यह काम नहीं करता है।
फुओक Huynh
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.