HttpServletRequest से POST अनुरोध निकाय प्राप्त करें


114

मैं HttpServletRequest ऑब्जेक्ट से पूरे शरीर को प्राप्त करने की कोशिश कर रहा हूं।

मैं जिस कोड का अनुसरण कर रहा हूं वह इस प्रकार है:

if ( request.getMethod().equals("POST") )
{
    StringBuffer sb = new StringBuffer();
    BufferedReader bufferedReader = null;
    String content = "";

    try {
        //InputStream inputStream = request.getInputStream();
        //inputStream.available();
        //if (inputStream != null) {
        bufferedReader =  request.getReader() ; //new BufferedReader(new InputStreamReader(inputStream));
        char[] charBuffer = new char[128];
        int bytesRead;
        while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 ) {
            sb.append(charBuffer, 0, bytesRead);
        }
        //} else {
        //        sb.append("");
        //}

    } catch (IOException ex) {
        throw ex;
    } finally {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException ex) {
                throw ex;
            }
        }
    }

    test = sb.toString();
}

और मैं कर्ल और विग के साथ कार्यक्षमता का परीक्षण कर रहा हूं:

curl --header "MD5: abcd" -F "fileupload=@filename.txt http://localhost:8080/abcd.html"

wget --header="MD5: abcd" --post-data='{"imei":"351553012623446","hni":"310150","wdp":false}' http://localhost:8080/abcd.html"

लेकिन while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 )कुछ भी वापस नहीं करता है, और इसलिए मुझे स्ट्रिंगरबफ़र पर कुछ भी नहीं मिला।

जवाबों:


191

जावा 8 में, आप इसे सरल और साफ तरीके से कर सकते हैं:

if ("POST".equalsIgnoreCase(request.getMethod())) 
{
   test = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
}

7
मैं इस समाधान को पसंद करता हूं, क्योंकि यह किसी भी तीसरे पक्ष की निर्भरता के बिना एक शुद्ध जावा है।
लू_को

49
हालांकि ध्यान रखें कि हम अनुरोध निकाय को फिर से नहीं पढ़ सकते हैं जैसा getReaderकि पहले ही कहा जा चुका है।
निखिल साहू

1
हम पुन: अनुरोध में नए स्वरूपित HTTP POST डेटा को फिर से कैसे सेट कर सकते हैं?
प्र ० ए ०

1
मैंने इस समाधान की कोशिश की है, लेकिन इसने एक बहुत ही गंभीर प्रस्तावना पेश की है, मैंने इस कोड का उपयोग एक बार एक सामान्य फ़िल्टर के अंदर अनुरोध जानकारी लॉग करने के लिए किया था, और जब मैंने इसका उपयोग किया, तो मेरे सभी पोस्ट विधियों में मेरे सभी @modelAttribute बाइंडिंग ने सभी के सभी क्षेत्रों में एक अशक्त कर दिया ऑब्जेक्ट। मैं इस दृष्टिकोण का उपयोग करने की अनुशंसा नहीं करता हूं।
मोहम्मद फ़ाठी

क्या हमें पाठक को बंद नहीं करना चाहिए?
aristo_sh

46

कॉमन्स-आईओ के साथ आसान तरीका।

IOUtils.toString(request.getReader());

https://commons.apache.org/proper/commons-io/javadocs/api-2.5/org/apache/commons/io/IOUtils.html


अगर आपको पाठक का आउटपुट कैसा लगेगा (यानी शो कीज़ या नहीं) तो इसका एक उदाहरण दे सकते हैं
आर्थरग

इसने मेरे लिए काम किया। मैं इस बात की पुष्टि कर सकता हूं कि यह समाधान एक सामान्य परिदृश्य से भी बचता है जहां कोई स्पष्ट कारण के लिए बफ़रड्रेडर.डरलाइन () "हैंग" होता है
नरेन

हाय @DavidDomingo, यह 100% काम करता है, मैं पढ़ सकता हूं कि आप इस एक के ऊपर प्रतिक्रिया में एक ही टिप्पणी कर रहे हैं (जो काम भी करता है)। जांचें कि कहीं आपके कोड में (संभावित रूप से फिल्टर), या शायद इसलिए कि स्प्रिंग द्वारा किसी को, गेटरीडर () विधि को पहले नहीं बुलाया जाता है, क्योंकि यदि आप इसे दो बार या अधिक बार कॉल करते हैं, तो यह केवल पहले वाले पेलोड को वापस करता है।
दानी

हाय @ दानी, इसीलिए यह काम नहीं करता। पाठक खाली है। मुझे लगता है कि रेस्टकंट्रोलर इसे किसी भी समापन बिंदु में करने में सक्षम होने से पहले पढ़ता है। HttpEntity का उपयोग करके शरीर को प्राप्त करने का सबसे आसान तरीका है।
डेविड डोमिंगो

31

ज्ञात हो, कि आपका कोड काफी शोर है। मुझे पता है कि धागा पुराना है, लेकिन बहुत सारे लोग इसे वैसे भी पढ़ेंगे। आप अमरूद पुस्तकालय का उपयोग करके एक ही काम कर सकते हैं :

    if ("POST".equalsIgnoreCase(request.getMethod())) {
        test = CharStreams.toString(request.getReader());
    }

3
शायद विचार करेंif(RequestMethod.POST.name().equalsIgnoreCase(...)) { ... }
Madbreaks

मुझे java.lang.IllegalStateException मिलती है: getReader () को इस अनुरोध के लिए पहले ही बुला लिया गया है
Pra_A

18

यदि आप चाहते हैं कि सभी POST अनुरोध निकाय हैं, तो आप इस तरह से एक विधि का उपयोग कर सकते हैं:

static String extractPostRequestBody(HttpServletRequest request) throws IOException {
    if ("POST".equalsIgnoreCase(request.getMethod())) {
        Scanner s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }
    return "";
}

इसका श्रेय: https://stackoverflow.com/a/5445161/1389219


1
खाते के request.getInputStream()चरित्र एन्कोडिंग के रूप में request.getReader()करता है कि सम्मान नहीं करता खाते में ले लो । हालांकि लिंक के लिए +1।
वडज़िम

PUT विधि के लिए समकक्ष क्या होना चाहिए?
देवनाथन

10

यह GET और POST दोनों के लिए काम करता है:

@Context
private HttpServletRequest httpRequest;


private void printRequest(HttpServletRequest httpRequest) {
    System.out.println(" \n\n Headers");

    Enumeration headerNames = httpRequest.getHeaderNames();
    while(headerNames.hasMoreElements()) {
        String headerName = (String)headerNames.nextElement();
        System.out.println(headerName + " = " + httpRequest.getHeader(headerName));
    }

    System.out.println("\n\nParameters");

    Enumeration params = httpRequest.getParameterNames();
    while(params.hasMoreElements()){
        String paramName = (String)params.nextElement();
        System.out.println(paramName + " = " + httpRequest.getParameter(paramName));
    }

    System.out.println("\n\n Row data");
    System.out.println(extractPostRequestBody(httpRequest));
}

static String extractPostRequestBody(HttpServletRequest request) {
    if ("POST".equalsIgnoreCase(request.getMethod())) {
        Scanner s = null;
        try {
            s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return s.hasNext() ? s.next() : "";
    }
    return "";
}

9

यदि अनुरोध बॉडी खाली है, तो इसका सीधा सा मतलब है कि पहले से ही इसका सेवन किया जा चुका है। उदाहरण के लिए, a request.getParameter(), getParameterValues()या getParameterMap()call के द्वारा। बस अपने कोड से उन कॉल करने वाली लाइनों को हटा दें।


यह केवल तभी काम करता है जब यह फ़ाइल अपलोड न हो, जैसा कि curlउदाहरण है, नहीं?
डेव न्यूटन

1
मैंने इस बात की कोशिश की। लेकिन फिर भी मुझे POST बॉडी नहीं मिल रही है। मेरा कुछ छूट रहा है। बस जोड़ने के लिए: मैं विकास के लिए टेपेस्ट्री का उपयोग कर रहा हूं।
पटेल

3

यह सभी HTTP विधि के लिए काम करेगा।

public class HttpRequestWrapper extends HttpServletRequestWrapper {
    private final String body;

    public HttpRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = IOUtils.toString(request.getReader());
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getBody().getBytes());
        ServletInputStream servletInputStream = new ServletInputStream() {
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {
            }

        };
        return servletInputStream;
    }

    public String getBody() {
        return this.body;
    }
}

0

मैंने उस स्थिति को इस तरह से हल किया। मैंने एक उपयोग विधि बनाई, जो ऑब्जेक्ट बॉडी से निकाले गए ऑब्जेक्ट को लौटाता है, ऑब्जेक्ट रीडर के रीडवेल विधि का उपयोग करके जो रीडर प्राप्त करने में सक्षम है।

public static <T> T getBody(ResourceRequest request, Class<T> class) {
    T objectFromBody = null;
    try {
        ObjectMapper objectMapper = new ObjectMapper();
        HttpServletRequest httpServletRequest = PortalUtil.getHttpServletRequest(request);
        objectFromBody = objectMapper.readValue(httpServletRequest.getReader(), class);
    } catch (IOException ex) {
        log.error("Error message", ex);
    }
    return objectFromBody;
}

1
PortalUtil क्या है?
फेरी क्रैननबर्ग

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