Я пытаюсь отправить двоичные данные с клиента с помощью 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' });
};
});