当我读到这样的数据时
String body = null;
try {
body = IOUtils.toString(request.getReader());
} catch (IOException e) {
//
}
并非所有数据都被读取。 “content-length”标题包含正确的数据长度,但看起来IOUtils.toString
不会等待所有的块。
这个旧的详细代码有效,但我想知道是否有一种现代方式等待读取所有数据:
String body = null;
try {
ServletInputStream in = request.getInputStream();
String reqLengthString = request.getHeader("content-length");
int requestLength = 0;
try {
requestLength = Integer.valueOf(reqLengthString).intValue();
} catch (Exception e) {
return doForecastErrorResponse(response,"Invalid Content Length");
}
Debug.logInfo("RequestLength: "+requestLength, MODULE);
int i = -1;
while (requestLength > 0) {
byte[] line = new byte[8192];
i = waitingReadLine(in, line, 0, 8192, requestLength);
requestLength -= i;
if (Debug.verboseOn()) {
Debug.logVerbose("remaining request length: "+requestLength, MODULE);
Debug.logVerbose("data this grab: "+new String(line), MODULE);
}
jb.append(new String(line));
}
body = jb.toString().trim();
if (Debug.verboseOn()) {
Debug.logVerbose("String: "+body, MODULE);
}
} catch (IOException e) {
return doForecastErrorResponse(response,"Error reading input."+e.getMessage());
}
private static int waitingReadLine(ServletInputStream in, byte[] buf, int off, int len, int reqLen) throws IOException {
int i = -1;
while (((i = in.readLine(buf, off, len)) == -1) && (reqLen > 0)) {
int waitCount = 0;
int MAX_WAITS = 30;
int WAIT_INTERVAL = 1000;
if (Debug.verboseOn()) Debug.logVerbose("Waiting for read line", MODULE);
if (waitCount > MAX_WAITS) {
if (Debug.verboseOn()) Debug.logVerbose("Waited " + waitCount + " times, bailing out while still expecting " + reqLen + " bytes.", MODULE);
throw new IOException("waited " + waitCount + " times, bailing out while still expecting " +
reqLen + " bytes.");
}
waitCount++;
long endMS = new Date().getTime() + WAIT_INTERVAL;
while (endMS > (new Date().getTime())) {
try {
Thread.sleep(WAIT_INTERVAL);
} catch (Exception e3) {
if (Debug.verboseOn()) Debug.logVerbose("Exception waiting for read line"+ e3.getMessage(), MODULE);
}
}
if (Debug.verboseOn()) Debug.logVerbose("Waited " + (new Date().getTime() - (endMS - WAIT_INTERVAL)) + " ms", MODULE);
}
return i;
}
更新:实际上诀窍是使用getInputStream
而不是getReader
:
IOUtils.toString(request.getInputStream());
张贴来自@John Bollinger的评论回答
byte[] buffer = new byte[requestLength];
IOUtils.readFully(request.getInputStream(), buffer);
body = new String(buffer);