当前位置: 首页 > 知识库问答 >
问题:

如何在不读取整个请求的情况下发送响应?

咸晨
2023-03-14

我正在基于Tomcat servlet和NIO创建服务。输入时有大的XML请求(约100 MB),通过HTML POST方法发送。我只想流前8千磅,然后立即发送响应到客户端。

public class A extends HttpServlet {
    @Override
    protected void service(HttpServletRequest rq, HttpServletResponse rs) {
        byte[] buffer = new byte[1024*8];
        try {
            rq.getInputStream().read(buffer);
            rs.setContentType("text/plain");
            rs.getOutputStream().write("Some Response".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } 
     }
}

当我尝试发送小请求(内容中只有几行)时,套接字工作正常。

2016-02-01 10:44:52 Http11NioProtocol[DEBUG]套接字:[org.apache.tomcat.util.net.NioEndpoint$KeyAttachment@74f19fed:组织。阿帕奇。公猫util。网NioChannel@c478210:java。nio。频道。SocketChannel[connected local=/0:0:0:0:0:0:1:8080 remote=/0:0:0:0:0:0:0:0:1:63943]],状态为:[OPEN\u READ],状态为:[OPEN]

但,若我尝试发送更大的请求(超过100MB),客户端并没有响应。

2016-02-01 10:48:42 Http11NioProtocol[DEBUG]套接字:[org.apache.tomcat.util.net.NioEndpoint$KeyAttachment@2b36c88f:组织。阿帕奇。公猫util。网NioChannel@25f12241:java。nio。频道。SocketChannel[connected local=/0:0:0:0:0:0:1:8080 remote=/0:0:0:0:0:0:0:0:1:64079]],状态为in:[OPEN\u READ],状态为out:[CLOSED]

2016-02-01 10:48:42超文本传输协议-Nio-8080-exec-3

在我读取整个输入流请求之前,Tomcat不想打开套接字(State out: CLOSED)。

是否可以在不读取整个请求的情况下将响应发送到客户端?根据规范,我能够在请求的前8 KiB上找到有趣的me信息。

共有1个答案

骆文华
2023-03-14

你的代码只是请求的一部分,

private static String convertStreamToString(InputStream is) throws IOException{
        int i = 0;
        byte[] buff = new byte[1024];
        StringBuilder sb = new StringBuilder();
        while (i != -1) {            
            i = is.read(buff);
            if(i != -1){
            sb.append(new String(buff,0,i));
            }
        }
        return sb.toString();
    }

所以,在你的代码中,它将是

public class A extends HttpServlet {
    @Override
    protected void service(HttpServletRequest rq, HttpServletResponse rs) {

        try {
            String response = convertStreamToString(rq.getInputStream());   
            rs.getOutputStream().write(response.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } 
     }
     private static String convertStreamToString(InputStream is) throws IOException{
        int i = 0;
        byte[] buff = new byte[1024];
        StringBuilder sb = new StringBuilder();
        while (i != -1) {            
            i = is.read(buff);
            if(i != -1){
                sb.append(new String(buff,0,i));
            }
        }
        return sb.toString();
    }

}

或者您可以使用Scanner直接将流转换为字符串

    Scanner scanner = new Scanner(inputStream);
    StringBuilder sb = new StringBuilder();
    while (scanner.hasNext()) {            
        sb.append(scanner.next());
    }

因此,在您的代码中应该是

public class A extends HttpServlet {
    @Override
    protected void service(HttpServletRequest rq, HttpServletResponse rs) {

        try {
             Scanner scanner = new Scanner(rq.getInputStream());
             StringBuilder sb = new StringBuilder();
             while (scanner.hasNext()) {            
                 sb.append(scanner.next());
             }
            rs.getOutputStream().write(sb.toString().getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } 
     }

}

此代码

byte[] buffer = new byte[1024*8];
rq.getInputStream().read(buffer);

只读取1024个字节的请求并将其存储到缓冲区数组(1024个字节),方法读取将返回读取的字节数,因为根本不会读取1024个字节,如果请求只发送200个字节,824个字节将无用。因此,如果请求只发送200字节

int x = rq.getInputStream().read(buffer);

这个x将是200,所以要完全阅读,你需要做一个循环

// integer to read
int bytesRead = 0;
// loop until bytesRead is -1 (end of request), -1 means there are no bytes to read, so it will read until there are no bytes to read
while(bytesRead != -1){
    bytesRead = rq.getInputStream().read(buffer);
    if(bytesRead != -1){
    // process the bytes here , but only process bytes from 0 to bytesRead
     }
}
 类似资料:
  • 问题内容: 是否有一种隐藏的方法可以在 不 读取整行的 情况下 从文件或类似文件的对象读取令牌?我立即拥有的应用程序(其他人的问题,不是我的问题)正在将具有几个非常长的行的大型矩阵转置,本质上是对选择单个列元素的迭代器执行操作。这个想法不是在迭代过程中将整个文件存储在内存中。 这些行是用空格分隔的ASCII十进制数字。 对于Java的Scanner类,问题可能很简单,但我没有在Python标准库中

  • (Java版本8) 我需要在过滤器中处理请求正文。使用下面的代码,我读取了正文。 问题是如果请求正文发布的参数的内容类型为“Application/x-www-form-urlencoded”,那么这些参数在读取正文后将不可用。如果我不读取正文,它们可以使用request.getParameter()获取。 此外,我尝试使用以下代码包装请求并提供正文,这样解决方案的其余部分(例如servlet)就

  • 我正在建立一个应用程序,用户将把他们的测试和作业和任何东西。我想知道我的应用程序是否有可能在测试前一周和一天发出通知? 我看到的到处都是firebase通知和push通知。 我不想要这些在线通知,我将需要应用程序发送他们自己离线。这可能吗?

  • 问题内容: 我有一个实现接口的类型,该接口在其方法中检查传入的HTTP请求,采取某些措施,然后将请求转发到反向代理处理程序()。 只要我仅检查基本的请求属性(例如URL或标头),此方法就可以正常工作。 当我想检查传入的POST请求的主体(例如,通过调用然后使用属性)时,将请求传递到反向代理后,就会遇到错误: 我认为发生这种情况是因为查看HTTP请求的正文会导致流被耗尽,这意味着代理处理程序无法再次

  • null 但是,当与HTTP1建立连接时,最后调用。 http1ExchangeCodeC.FixedLengthSource::Close 然后,方法读取所有响应体源,如下所示。

  • 问题内容: 我只是想知道是否可以在不将Outlook安装在服务器上且不使用COM Interop的情况下向人们发送会议请求(我不惜一切代价避免在服务器上使用)。 我们在Windows 2003域中拥有Exchange 2003,并且所有用户都是域用户。我想我可以发送’round iCal / vCal之类的东西,但是我想知道是否存在通过Exchange在不使用Outlook的情况下发送会议请求的适