如何在 httpcomponents NIO 服务器中以块的形式读取请求?

how to read the request in chunks in httpcomponents NIO server?

我正在使用 httpcomponenets nio 服务器来处理 post 请求。

下面是示例代码。它使用 EntityUtils.toByteArray() 获取字节数组中的完整数据。如果请求者发送一个大文件,这将失败。

我不知道如何分块读取请求中的数据。 HttpEntity.getContent().read() 总是 returns null

    public static void main(String[] args) throws Exception {
       int port = 8280;

       // Create HTTP protocol processing chain
       HttpProcessor httpproc = HttpProcessorBuilder.create()
           .add(new ResponseDate())
           .add(new ResponseServer("Test/1.1"))
           .add(new ResponseContent())
           .add(new ResponseConnControl()).build();
       // Create request handler registry
       UriHttpAsyncRequestHandlerMapper reqistry = new UriHttpAsyncRequestHandlerMapper();
       // Register the default handler for all URIs
       reqistry.register("/test*", new RequestHandler());
       // Create server-side HTTP protocol handler
       HttpAsyncService protocolHandler = new HttpAsyncService(httpproc, reqistry) {

           @Override
           public void connected(final NHttpServerConnection conn) {
               System.out.println(conn + ": connection open");
               super.connected(conn);
           }

           @Override
           public void closed(final NHttpServerConnection conn) {
               System.out.println(conn + ": connection closed");
               super.closed(conn);
           }

       };
       // Create HTTP connection factory
       NHttpConnectionFactory<DefaultNHttpServerConnection> connFactory;

           connFactory = new DefaultNHttpServerConnectionFactory(
               ConnectionConfig.DEFAULT);
       // Create server-side I/O event dispatch
       IOEventDispatch ioEventDispatch = new DefaultHttpServerIODispatch(protocolHandler, connFactory);
       // Set I/O reactor defaults
       IOReactorConfig config = IOReactorConfig.custom()
           .setIoThreadCount(1)
           .setSoTimeout(3000)
           .setConnectTimeout(3000)
           .build();
       // Create server-side I/O reactor
       ListeningIOReactor ioReactor = new DefaultListeningIOReactor(config);
       try {
           // Listen of the given port
           ioReactor.listen(new InetSocketAddress(port));
           // Ready to go!
           ioReactor.execute(ioEventDispatch);
       } catch (InterruptedIOException ex) {
           System.err.println("Interrupted");
       } catch (IOException e) {
           System.err.println("I/O error: " + e.getMessage());
       }
       System.out.println("Shutdown");
   }
public static class RequestHandler implements HttpAsyncRequestHandler<HttpRequest> {
   public void handleInternal(HttpRequest httpRequest, HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException {

       HttpEntity entity = null;
       if (httpRequest instanceof HttpEntityEnclosingRequest)
           entity = ((HttpEntityEnclosingRequest)httpRequest).getEntity();

       byte[] data;
       if (entity == null) {
           data = new byte [0];
       } else {
           data = EntityUtils.toByteArray(entity);
       }

       System.out.println(new String(data));

       httpResponse.setEntity(new StringEntity("success response"));
   }

   @Override public HttpAsyncRequestConsumer<HttpRequest> processRequest(HttpRequest request, HttpContext context) throws HttpException, IOException {
       return new BasicAsyncRequestConsumer();
   }

   @Override
   public void handle(HttpRequest request, HttpAsyncExchange httpExchange, HttpContext context) throws HttpException, IOException {
       HttpResponse response = httpExchange.getResponse();
       handleInternal(request, response, context);
       httpExchange.submitResponse(new BasicAsyncResponseProducer(response));

   }
}

如果您想完全控制请求处理,请考虑实施自定义 AbstractAsyncRequestConsumer 而不是 BasicAsyncRequestConsumer

您可以使用这些 类 作为起点 [1][2]。请注意,这些是 response 消费者,尽管可以使用 相同的方法 创建自定义请求消费者:

[1] http://hc.apache.org/httpcomponents-asyncclient-4.1.x/httpasyncclient/xref/org/apache/http/nio/client/methods/AsyncCharConsumer.html

[2] http://hc.apache.org/httpcomponents-asyncclient-4.1.x/httpasyncclient/xref/org/apache/http/nio/client/methods/AsyncByteConsumer.html