我希望能够将整个请求写入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(),但效果相同。
答案 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控制器中将其作为请求属性获取,最后获取请求主体的副本。