Spring Boot Websockets: не удается получить двоичные данные в правильной форме в Spring Controller - PullRequest
0 голосов
/ 11 марта 2019

Я пытаюсь отправить двоичные данные с клиента с помощью webstomp-client js на сервер Spring. На стороне клиента я могу убедиться, что отправляемое тело данных действительно является массивом байтов.

Однако, когда это получено в моем контроллере websocket, (через класс Message в моем вызове метода) полезная нагрузка представляет собой двоичный файл, который является строковым преобразованием [Object ArrayBuffer]

вот код для конфигурации websocket

@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfig2
    implements WebSocketMessageBrokerConfigurer {

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

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/connect")
            .setHandshakeHandler(new DefaultHandshakeHandler() {

                public boolean beforeHandshake(
                        ServerHttpRequest request,
                        ServerHttpResponse response,
                        WebSocketHandler wsHandler,
                        Map attributes) throws Exception {

                    if (request instanceof ServletServerHttpRequest) {
                        ServletServerHttpRequest servletRequest
                                = (ServletServerHttpRequest) request;
                        HttpSession session = servletRequest
                                .getServletRequest().getSession();
                        attributes.put("sessionId", session.getId());
                    }
                    return true;
                }}).setAllowedOrigins("*")  ;
    }
}

вот мой контроллер

@MessageMapping("/files")
@SendToUser("/queue/reply")
public String processFileFromClient(Message message, Principal principal) throws Exception {
    // this payload is bytes that convert to "[Object ArrayBuffer]"
    byte[] payload = (byte[]) message.getPayload();
    return "Message Received" + message.toString();
}

вот мой клиент

files.forEach((File) => {
    reader.readAsArrayBuffer(File);
    reader.onloadend = () => {};
    reader.onload = (e) => {
      console.log('file loaded');
      arrayBuffer = e.target.result;
      self.uploadWS.send('/ws/uploadFiles', arrayBuffer, { 'Content-Type': 'application/octet-stream' });
    };

Обновление

Я попытался преобразовать ArrayBuffer на стороне клиента в Uint8Array, и я вижу байтовый массив, поступающий от клиента, однако во время преобразования на сервере обратно в файл я все еще получаю ошибки.

Я подтвердил, что файл не поврежден, и я также настроил другую конфигурацию веб-сокета, не используя stomp, которая может обрабатывать файл с помощью API веб-сокета на клиентском компьютере js и обрабатывать BinaryMessage в пользовательском WebsocketHandler ... однако я предпочел бы использовать stomp для создания каналов подписки для разделения сообщений через контроллер.

Для справки это конфигурация websocket без использования stomp

@Configuration
@EnableWebSocket
public class WebsocketConfig1 implements WebSocketConfigurer {

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    registry.addHandler(fileHandler(),"/ws/upload").setAllowedOrigins("*");
}

@Bean
public WebSocketHandler myHandler() {
    return new MyHandler();
}

@Bean
public WebSocketHandler fileHandler() {
    return new FileHandler();
}

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

}

для справки: это обработчик, созданный для файла, когда я не использую stomp и контроллер (который позволяет отправлять правильные двоичные данные для обеспечения безошибочного преобразования данных)

@Override
public void handleBinaryMessage(WebSocketSession session, BinaryMessage msg){
    try {
        int payloadLength = msg.getPayloadLength();
        session.sendMessage(new TextMessage("Receiving Data " + payloadLength));
        File file = amazonClient.convertbyteArrayToFile(msg.getPayload().array(), "ExcelSpreadSheet");

            FileMetadataSpreadsheet metadataSpreadsheet = metadataParser.parse(file);
            session.sendMessage(new TextMessage("Metadata SpreadSheet Parsed"));

                for(Map.Entry entrySet : metadataSpreadsheet.getMetadataMap().entrySet()){
                    session.sendMessage(new TextMessage(entrySet.getKey().toString() + entrySet.getValue().toString()));

                }
    } catch (Exception e) {
        log.error(e.getMessage());
    }
}

это код для преобразования из ArrayBuffer в Uint8Array в клиенте

files.forEach((File) => {
    reader.readAsArrayBuffer(File);
    reader.onloadend = () => {};
    reader.onload = (e) => {
      console.log('file loaded');
      arrayBuffer = e.target.result;
      const intArray = new Uint8Array(arrayBuffer);
      self.uploadWS.send('/ws/uploadFiles', intArray, { 'Content-Type': 'application/octet-stream' });
    };
  });
...