According to the onMessage
javadoc,
both onMessage(byte[] b)
and onMessage(InputStream is)
will receive the whole message:
if the method is handling binary messages:
- byte[] or ByteBuffer to receive the whole message
- InputStream to receive the whole message as a blocking stream
So, if you use one of these methods, Jetty will automatically reassemble the chunks and deliver the whole message to your method (as a byte[]
array or an InputStream
).
The maximum size of the binary message, you can receive this way, is set with the setMaxBinaryMessageSize
Also note, that you may only have one of these methods defined at your Handler class at once:
Each websocket endpoint may only have one message handling method for each of the native websocket message formats: text, binary and pong.
If you want to process the data as it goes, you should use the following method signature instead:
@OnMessage
public void processUpload(byte[] b, boolean last, Session session) {
// process partial data here, which check on last to see if these is more on the way
}
and manually buffer your data (in memory or disk file e.t.c.)
The client, in turn, should use one of sendPartialBytes methods, to send the data chunk by chunk.
If what you observe is the "whole message" method (i.e. onMessage(byte[] b
) being invoked for an each data chunk, as send by the client, this indicates that the client is not utilizing the protocol capabilities to send chunked messages, and does instead split the input data and then sends its parts as independent WS messages, effectively creating it's own application level protocol for transmitting the data in chunks.
In this case, you must either update the client (if that is an option),
to make it use a regular WS protocol capabilities, or implement the same "application level protocol" the client is using.
Below is a super-simple endpoint example, which will buffer the input data
until the WS socket is closed (this implies that client will close the connection once it has sent all the chunks).
@ServerEndpoint("/data")
public static class Handler {
private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
@OnMessage
public void onMessage(byte[] message) throws IOException {
buffer.write(message);
}
@OnClose
public void onClose(Session session) throws IOException {
System.out.println(
buffer.toByteArray().length
);
}
}
This implementation also implies that a default ServerEndpointConfig.Configurator is used, so that there is exactly one Endpoint instance per connection (as documented here).
A more complex implementation might want to reuse the socket to send multiple files, and specify a mechanism to denote the start and end of each transmission (e.g. with a specially formatted message), but it all depends on how your client is implemented.