【发布时间】:2019-07-26 08:10:57
【问题描述】:
当我读到这样的数据时
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;
}
【问题讨论】:
-
您可以尝试使用
IOUtils.readFully()方法之一将数据读入Buffer或数组,然后将结果转换为String。 -
你要读取什么数据?
-
@ScaryWombat 它是一个 JSON 对象
-
@JohnBollinger 我将 char[] 的大小设置为什么?如果我将它设置为内容长度,我会报错
java.io.EOFException: Length to read: 11912 actual: 8129我认为块大小是 8129 -
@SumamaWaheed,内容长度给出了 bytes 的长度,而不是字符。 (编码)字符的数量不一定相同。目前尚不清楚是否可以通过此路线获得解决方案,但如果是,那么您可能应该将
content-lengthbytes 读入字节数组,然后将结果转换为String根据到客户端指定的编码,或者根据相应的网络协议的默认编码,不一定是Java的默认编码。
标签: java apache http tomcat servlets