在Spring MVC中写入文件请求

时间:2011-07-28 08:58:16

标签: java spring servlets spring-mvc

我希望能够将整个请求写入Spring MVC控制器中的文件。

我尝试过以下操作,但即使我正在使用大量参数发出POST请求,文件仍然是空的:

    @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);
    }
}

我也尝试过使用HttpServletRequest.getInputStream(),但效果相同。

2 个答案:

答案 0 :(得分:7)

使用InputStream不起作用(参见BalusC的回答)。下面是一个如何使用HTTPServletRequest对象来编写标题和参数的示例:

@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);
    }
}

答案 1 :(得分:5)

我对Spring一无所知,但我至少可以告诉POST请求正文只能读一次。它就是客户端发送到服务器的数据。只要服务器需要多次,客户端就不会多次重新发送它。

我假设Spring已经读取了请求体,以便在进入Spring控制器方法之前解析所包含的查询字符串并获取请求参数。这可以在Spring的封面下用request.getParameter()和consorts完成。在Servlet API中,一旦调用了该方法,request.getInputStream()request.getReader()之后就不会返回任何内容。只是因为已经读取了请求体以返回参数。 getParameter()'s javadoc中也提到了这一点。

  

如果参数数据是在请求正文中发送的,例如HTTP POST请求,则直接通过getInputStream()getReader()读取正文会干扰此方法的执行。

最好的办法是创建一个filter,在Spring完成工作之前复制请求体,然后将过滤器放在Spring控制器前面。在HttpServletRequestWrapper的帮助下,可以复制请求正文,其中您覆盖getInputStream()getReader()方法,首先将请求正文读入ByteArrayInputStream和/或CharArrayReader以便您拥有本地副本,然后将其返回。对HttpServletRequestWrapper的引用可以存储为请求属性,以便您可以在Spring控制器中将其作为请求属性获取,最后获取请求主体的副本。