Spring Boot Websockets:无法在Spring Controller中以正确的形式接收二进制数据

时间:2019-03-11 18:06:59

标签: spring-boot websocket binary-data spring-websocket web-stomp

我正在尝试使用webstomp-client js从客户端向二进制服务器发送二进制数据。在客户端,我可以验证所发送的数据主体确实是字节数组缓冲区。

但是,当在我的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的websocket配置,该配置能够在客户端js上使用websocket api并在自定义WebsocketHandler中处理BinaryMessage来处理文件...但是我宁愿使用stomp创建订阅通道来通过控制器分隔消息。

作为参考,这是不使用stomp的websocket配置

@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;
}

}

这是供参考,这是当我不使用脚踩和控制器时为文件创建的处理程序(它允许发送正确的二进制数据以允许数据的无错误转换)

@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' });
    };
  });

0 个答案:

没有答案