Write a file request in Spring MVC

I would like to write the entire file request in the Spring MVC controller.

I tried the following, but the file is always empty, although I am making a POST request with many parameters:

@RequestMapping(method = RequestMethod.POST, value = "/payments/confirm") public void receiveCallback(ServletInputStream inputStream) { try { inputStream.reset(); byte[] data = IOUtils.toByteArray(inputStream); File file = new File(System.getProperty("java.io.tmpdir") + "test" + System.currentTimeMillis() + ".txt"); FileOutputStream fos = new FileOutputStream(file); fos.write(data); fos.close(); } catch (Exception e) { logger.error("Error writing request", e); } } 

I also tried using HttpServletRequest.getInputStream (), but the same results.

+4
source share
2 answers

Using InputStream will not work (see BalusC answer). Here is an example of how you could use the HTTPServletRequest object instead of writing headers and parameters:

 @RequestMapping(method = RequestMethod.POST, value = "/payments/confirm") public void receiveCallback(HttpServletRequest request) { try { StringBuilder sb = new StringBuilder(); sb.append("Headers:\n"); Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String headerName = headerNames.nextElement(); Enumeration<String> headers = request.getHeaders(headerName); while (headers.hasMoreElements()) { String headerValue = headers.nextElement(); sb.append(headerName).append(':').append(headerValue).append('\n'); } } sb.append("\nParameters:\n"); for(Entry entry: (Set<Entry>) request.getParameterMap().entrySet(){ sb.append(entry.getKey()).append(':').append(entry.getValue()).append('\n'); } byte[] data = sb.toString().getBytes(); File file = new File(System.getProperty("java.io.tmpdir") + "test" + System.currentTimeMillis() + ".txt"); FileOutputStream fos = new FileOutputStream(file); fos.write(data); fos.close(); } catch (Exception e) { logger.error("Error writing request", e); } } 
+7
source

I don't know anything about Spring, but I can at least say that the body of a POST request can be read only once . This is exactly the data that the client sent to the server. The client is not going to resend it several times when the server needs it several times.

I assume that Spring has already read the request body to parse the closed request string and get the request parameters before entering the Spring controller method. This can be done with Spring coverage using request.getParameter() and spouses. In the Servlet API, once this method has been called, request.getInputStream() and request.getReader() will not return anything else. Just because the request body has already been read to return the parameters. This is also mentioned in getParameter() javadoc .

If the parameter data was sent to the request body, for example, with an HTTP POST request, then reading the body directly through getInputStream() or getReader() may interfere with the execution of this method.

It is best to create a filter that will make a copy of the request body before Spring does its work, and then place the filter in front of the Spring controller. Creating a copy of the request body is possible using HttpServletRequestWrapper , in which you override the getInputStream() and getReader() methods for the first reading of the request body in ByteArrayInputStream and / or a CharArrayReader , so that you have a local copy and then return it. The reference to the HttpServletRequestWrapper can be saved as a request attribute so that you can get it as a request attribute in the Spring controller and finally get a copy of the request body.

+5
source

All Articles