将二进制数据stompClient发送到Spring-websocket控制器并消耗

时间:2015-06-16 13:56:32

标签: spring stomp spring-websocket stompjs

我想将stompClient中的二进制数据发送到spring控制器。 这是我的JS

var socket = new SockJS('/test/binary');
        var stompClient = Stomp.over(socket);

        socket.binaryType = "arraybuffer";
        var appModel = new ApplicationModel(stompClient);
        ko.applyBindings(appModel);

        appModel.connect();
        appModel.pushNotification("Notifications.");


 var ctx =   canvas.get()[0].getContext('2d');
 ctx.drawImage(img, 0, 0, 320, 240);
 var data  = canvas.get()[0].toDataURL('image/jpeg', 1.0);
 newblob = dataURItoBlob(data);


 stompClient.send("/app/vid", {},  newblob);

function dataURItoBlob(dataURI) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
        else
        byteString = unescape(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

   return new Blob([ia], {type:mimeString});

我试过发送Blob,Uint8Array发送的消息但是在服务器端我无法使用它。 我在控制器中的方法是:

@MessageMapping("/vid")
public void getVid(Message<byte[]> message, Principal principal) throws IOException {
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
bOut.write(message.getPayload());
bOut.flush();
byte[]  imageInByte = bOut.toByteArray();
bOut.close();

InputStream in = new ByteArrayInputStream(imageInByte);
BufferedImage bImageFromConvert = ImageIO.read(in);

ImageIO.write(bImageFromConvert, "jpeg", new File(
        "E:/new-darksouls.jpg"));

template.convertAndSend("/topic/binarydemo2",   message);

我使用了ByteArrayMessageConverter,StringMessageConverter,MappingJackson2MessageConverter和我写的Base64JavaObjectMessageConverter:

public class Base64JavaObjectMessageConverter extends AbstractMessageConverter {

public Base64JavaObjectMessageConverter() {
    super(MimeTypeUtils.APPLICATION_OCTET_STREAM);
}

@Override
protected boolean supports(Class<?> clazz) {
    return true;
}


@Override
public Object convertFromInternal(Message<?> message, Class<?> targetClass) {
    byte[] messageBytes =Base64Utils.decode( (byte[])message.getPayload() );
    return SerializationUtils.deserialize( messageBytes  );
}

@Override
public Object convertToInternal(Object payload, MessageHeaders headers) {
    byte[] messageBytes = SerializationUtils.serialize( payload );
    return Base64Utils.encode( messageBytes);
}

}

我只能将byte []发送为字符串,从中删除'base64'等:

stompClient.send("/app/vid", {},   data.split(',')[1]);

在控制器中:

@MessageMapping("/vid")
public void getVid(String message, Principal principal) throws IOException {


    byte[] bytearray = Base64.decode(message);
    BufferedImage imag=ImageIO.read(new ByteArrayInputStream(bytearray));

    ImageIO.write(imag, "jpg", new File("E:/new-darksouls.jpg"));

但这不是我想要实现的目标。我认为这将取决于性能。

我正在使用Spring 4.2.0.RC1 WebSockets,StompJS 我在不同的帖子上看到,可以从后端发送到客户端和客户端到后端,但我无法重现它。如果我能得到一个具体的例子,如何在客户端上构建和发送Uint8Array或blob以及如何在服务器端处理它,我将非常感激。

感谢您的时间和帮助

1 个答案:

答案 0 :(得分:0)

SockJS不支持发送二进制数据。您可以通过普通WebSocket使用STOMP发送二进制消息。

在服务器端,请参阅StompSubProtocolHandler,它检查传入的消息是二进制还是文本,因此可以处理。从那里它并不重要,即从STOMP的角度来看,body是一个字节数组,而content-type / content-length头确定了body包含什么以及它应该如何被解释。在发送端,StompSubProtocolHandler也可以发送二进制文件或文本,如果内容类型是application / octet-stream并且只要没有使用SockJS,它现在使用二进制文件。

因此,简而言之,它应该可以工作,但不能在使用SockJS作为传输时使用。