Search code examples
javaniomultipartform-datanonblocking

How can I handle multipart form data in Java NIO Htttp Server


I have implemented a Non Blocking Htttp Server by using Java NIO. It works fine for x-www-form-urlencoded POST requests. But when i try it for a HTTP multipart request with large file, it is not working. In that situation Server unable to make response to http client. This is my source code for the NIO Server.

public class TCPServer {

    public static void main(String[] args) {
       TCPServer server = new TCPServer();
       server.listen();
    }

    public void listen() {

        try {

             Selector selector = Selector.open();

             ServerSocketChannel serverSocketChannel = ServerSocketChannel
                .open();

             InetSocketAddress serverAddress = new InetSocketAddress(8080);

             serverSocketChannel.bind(serverAddress);

             serverSocketChannel.configureBlocking(false);

             serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

             while (true) {

                  selector.select();

                  Set<SelectionKey> selectionKeys = selector.selectedKeys();
                  Iterator<SelectionKey> iterator =  selectionKeys.iterator();

                  while (iterator.hasNext()) {
                      SelectionKey key = iterator.next();

                      if (key.isAcceptable()) {
                          SocketChannel clientSocketChannel =  serverSocketChannel.accept();

                       clientSocketChannel.configureBlocking(false);

                       clientSocketChannel.register(selector,
                            SelectionKey.OP_READ);

                      } else if (key.isReadable()) {
                           SocketChannel clientSocketChannel = null;
                           try {
                               clientSocketChannel = (SocketChannel) key.channel();

                               ByteBuffer clientBuffer = ByteBuffer.allocate(1024);

                               StringBuilder requestStringBuilder = new StringBuilder();

                                int bytesRead = clientSocketChannel
                                .read(clientBuffer); 

                                while (bytesRead > 0) {

                                     clientBuffer.flip();

                                     String result = new String(clientBuffer.array());
                                     requestStringBuilder.append(result);

                                     clientBuffer.compact();

                                     bytesRead = clientSocketChannel.read(clientBuffer);

                                }

                                System.out.println("request-----");
                                System.out
                                  .println(requestStringBuilder.toString());

                                clientSocketChannel.write(ByteBuffer
                                  .wrap("reply from server".getBytes()));

                                clientSocketChannel.register(selector,
                                SelectionKey.OP_WRITE);
                    } catch (Exception e) {
                        System.err.println(e.getMessage());
                        clientSocketChannel.close();
                    }

                } else if (key.isWritable()) {
                    SocketChannel clientSocketChannel = null;
                    try {
                        clientSocketChannel = (SocketChannel) key.channel();
                        clientSocketChannel.close();
                    } catch (Exception e) {
                        System.err.println(e.getMessage());
                        clientSocketChannel.close();
                    }
                }
                iterator.remove();

            }
          }
        }catch (Exception e) {
             System.err.println(e.getMessage());
        }

    }

 }

Is there any other way to handle HTTP multipart request inside Java NIO non blocking server.How can i fix this. Thanks.


Solution

  • This is similar to another question: Servlet 3.1 - Multipart async processing, but I'll answer here as the solution works with plain non-blocking IO too.

    Synchronoss Technologies recently open sourced a non-blocking HTTP multipart parser here.

    As your non-blocking server receives data, you just need to pass the incoming bytes to the NioMultipartParser. The parser will make callbacks to your code for each of the parts received.

    Disclaimer: I work for Synchronoss Technologies. We wrote this for Servlet 3.1 but it should intentionally work in regular non-blocking applications too, so hopefully others will find this library useful.