8

I'm trying to send a file using websocket connection to my server: I've implemented the websocket server side using java Spring the client side is in javaScript for some reason each time i send a binary message from client side using "blob" or "arraybuffer. the server recognise the message as text message not as binary. what am i missing here?

Client Side

 <!DOCTYPE HTML>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            <title>Chat</title>
        </head>
    <body>
        <h2>File Upload</h2>
            Select file
        <input type="file" id="filename" />
        <br><br><br>
        <input type="button" value="Connect" onclick="WebSocketTest()" />
        <br><br><br>
        <input type="button" value="Upload" onclick="sendFile()" />

    <script>
    "use strict"
    var ws;
    function WebSocketTest()
    {
      if ("WebSocket" in window)
      {
         console.log("WebSocket is supported by your Browser!");
         // Let us open a web socket
         ws = new WebSocket("ws://xx.xx.xx.xx:yyyy/service/audioHandler");
         ws.onopen = function()
         {
            // Web Socket is connected, send data using send() 
            ws.send(JSON.stringify({userName:'xxxx',password:'sgdfgdfgdfgdfgdf'}));
            console.log("Message is sent...");
         };
         ws.onmessage = function (evt)
         {
            var received_msg = evt.data;
            console.log("Message is received...");
         };
         ws.onclose = function()
         {
            // websocket is closed.
            console.log("Connection is closed...");
         };
      }
      else
      {
         // The browser doesn't support WebSocket
         console.log("WebSocket NOT supported by your Browser!");
      }
    }

function sendFile() {
    var file = document.getElementById('filename').files[0];
    ws.binaryType = "arraybuffer";
    //ws.send('filename:'+file.name);
    var reader = new FileReader();
    var rawData = new ArrayBuffer();           
    console.log(file.name);
    reader.loadend = function() {
    }
    reader.onload = function(e) {
        rawData = e.target.result;
        ws.send(rawData);
        console.log("the File has been transferred.")
        //ws.send('end');
    }
    reader.readAsArrayBuffer(file);
}   
</script>
</body>
</html>

Server Side

public class WebSocketController extends BinaryWebSocketHandler {

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private CallScopeStore callScopeStore;

    private static Logger logger = Logger.getLogger(AudioHandler.class);
    private static final String STOP_MESSAGE = "stop";

    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
        try {
         //do something....
        } catch (Exception e) {
            logger.error(e, e);
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void handleTextMessage(final WebSocketSession session, TextMessage message) {
        try {
            //do something....
            }
        } catch (Exception e) {
            logger.error(e, e);
            throw new RuntimeException(e);

        }
    }
}
Alex
  • 11,115
  • 12
  • 51
  • 64
snabel
  • 343
  • 1
  • 2
  • 15
  • Try to send `Blob`, now you send `ArrayBuffer`, and may be you need to override MIME type of request – Alex Jan 15 '15 at 08:34
  • i tried this method: function sendFileBlob() { var file = document.getElementById('filename').files[0]; ws.binaryType = "blob"; ws.send(file);} And the connection was closed with this Error: CloseStatus[code=1009, reason=No async message support and buffer too small. Buffer size: [8,192], Message size: [7,816,684]] – snabel Jan 15 '15 at 08:48
  • it seems, i need to stream the file as chunks, do you know how to do that? – snabel Jan 15 '15 at 09:55
  • If you will create a live example, I will try – Alex Jan 15 '15 at 09:56
  • Related: https://stackoverflow.com/questions/21730566/how-to-increase-output-buffer-for-spring-sockjs-websocket-server-implementation – flaviut May 31 '19 at 02:36

2 Answers2

6

You have to send the file as a blob.

ws = new WebSocket("ws://xx.xx.xx.xx:yyyy/service/audioHandler");
ws.binaryData = "blob";
ws.send(message); // Blob object

Probably you can find an error as you mention: "CloseStatus[code=1009, reason=No async message support and buffer too small. Buffer size: [8,192], Message size: [7,816,684]]". That happens because your WebSocket Engine need to be configured to allow binary message with the size you want. For example, in your WebSocketConfig:

@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
    ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
    container.setMaxTextMessageBufferSize(500000);
    container.setMaxBinaryMessageBufferSize(500000);
    return container;
}

As you can see, you can set the maximun size allowed for your text and binary messages, just specify a size bigger than 7,816,684 (the file you was trying to send). By default, your buffer size is [8,192] so if you send a file with a smaller size than your buffer size, there shouldn't be problems. For more information, you can check websocket spring documentation.

robert08
  • 161
  • 1
  • 4
1
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
    ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
    container.setMaxTextMessageBufferSize(500000);
    container.setMaxBinaryMessageBufferSize(500000);
    return container;
}

WebSocketMessageBroker invalid. @robert08

@Configuration
@EnableWebSocketMessageBroker
public class MyWebSocketMessageBrokerConfigurer implements WebSocketMessageBrokerConfigurer {


    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/portfolio").setAllowedOrigins("*");
    }


    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.setPathMatcher(new AntPathMatcher("."));
        config.setApplicationDestinationPrefixes("/app");
        config.enableSimpleBroker("/topic", "/queue");
    }


    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration webSocketTransportRegistration) {
        webSocketTransportRegistration
                .setMessageSizeLimit(1024 * 1024)
                .setSendBufferSizeLimit(1024 * 1024 );

    }


}
Yi Li
  • 21
  • 2