How to send an image from server to client with Web Socket using Java / Javascript?

Frank :

I'm developing an app that sends an image from server to client with Web Socket, it seems the data was sent, but the image is not showing up in the html page.

I've searched the web for solutions, including Receive Blob in WebSocket and render as image in Canvas and How to send an image from a Java websocket server to use in an HTML5 canvas?

The connection is established properly, and I can even draw a rectangle in the html canvas, but nothing I've tried so far can solve my problem [ send over an image ], my code looks like this :

Server Side :

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Random;
import javax.imageio.ImageIO;

public class Image_Getter
{
    int W,H,g,b;
  BufferedImage Buffered_Image = null;
    String Image_Path="C:/Dir_WebSocket_Jetty/demo.png";

    public Image_Getter(int W,int H)
  {
        this.W=W;
        this.H=H;
    Buffered_Image = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB);
  }

  BufferedImage getAnImage()
  {
    try
        {
//          image = ImageIO.read(new File("image.jpg"));
            int x_1=getRandomNumber(0,W/2),x_2=getRandomNumber(W/2,W),r=getRandomNumber(0,230),g=getRandomNumber(60,230),b=getRandomNumber(90,250);
            for (int x=0;x<W;x++)
                if (x < x_1 || x_2 < x) for (int y=0;y<H;y++)   setColor(x,y,getRandomNumber(0,253),getRandomNumber(0,253),getRandomNumber(0,253),getRandomNumber(0,253));
                else for (int y=0;y<H;y++) setColor(x,y,r,g,b,253);
            ImageIO.write(Buffered_Image,"png",new File(Image_Path));
        }
        catch (Exception e) {   System.out.println("Error : " + e.getMessage());    }
    return Buffered_Image;
  }

    void setColor(int x,int y,int r,int g,int b,int a)   // r,g,b,a [ alpha (transparency) ] : 0 .. 255
    {
        int col = (a << 24) | (r << 16) | (g << 8) | b;
        Buffered_Image.setRGB(x,y,col);
    }

  int getRandomNumber(int min,int max)
  {
    int range=max-min+1,rand=(int)(Math.random()*range)+min; 
    return rand;
  }

  private static void out(String message) { System.out.print(message); }
  private static void Out(String message) { System.out.println(message); }
}

=============================================================

    Session s = sMap.get(key);

    if (s.isOpen())
    {
      BufferedImage image = image_getter.getAnImage();
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ImageIO.write(image,"jpg",baos);
      byte[] byteArray = baos.toByteArray();
   // s.getBasicRemote().sendText();  // connection.sendMessage(byteArray, 0, byteArray.length);

      String base64String = Base64.encode(byteArray);

      s.getBasicRemote().sendText(base64String);
   // s.getBasicRemote().sendBinary(Base64.encode(byteArray));
   // s.getBasicRemote().sendBinary(ByteBuffer.wrap(byteArray));

    }

Client side javascript :

class WebSocketImageClient
{
  constructor(protocol, hostname, port, endpoint)
  {
    this.webSocket = null;
    this.protocol = protocol;
    this.hostname = hostname;
    this.port = port;
    this.endpoint = endpoint;
  }

  getServerUrl() { return this.protocol + "://" + this.hostname + ":" + this.port + this.endpoint; }

  present() { return "Image Url = [ <font color=#0022CC>" + this.getServerUrl() + "</font> ]"; }

  connect()
  {
    var canvas = document.getElementById("imageCanvas");
    var context = canvas.getContext("2d");

    try
    {
      this.webSocket = new WebSocket(this.getServerUrl());
//      this.websocket.binaryType = "arraybuffer";

      // Implement WebSocket event handlers!
      this.webSocket.onopen = function (event)
      {
        console.log('onopen :: ' + JSON.stringify(event, null, 4));
      };

      this.webSocket.onmessage = function (event)
      {
        var msg = event.data;
        console.log('onmessage ::  ' + JSON.stringify(msg, null, 4));
//        var imageoutput = document.getElementById("imageCanvas");
/*
          var image = new Image();
          image.src = msg;
//          image.data = msg;
           image.onload = function() {
          context.drawImage(image, 0, 0);
          };
*/
        if (msg)
        {

          if (msg instanceof Blob)
          {
            var blob = msg;

            var bytes = new Uint8Array(blob);
            var image = context.createImageData(canvas.width, canvas.height);
            for (var i = 0; i < bytes.length; i++)
            {
              image.data[i] = bytes[i];
            }
//            alert("image = "+image);
            context.drawImage(image, 0, 0);
          }

        }
//        context.fillStyle = "#0000DD";
//        context.fillRect(160, 60, 36, 36);                // This can draw a rectangle
//        imageoutput.innerHTML = msg;

      };
      this.webSocket.onclose = function (event)
      {
        console.log('onclose :: ' + JSON.stringify(event, null, 4));
      };
      this.webSocket.onerror = function (event)
      {
        console.log('onerror :: ' + JSON.stringify(event, null, 4));
      };

    }
    catch (exception)
    {
      console.error(exception);
    }
  }

  getStatus()
  {
    return this.webSocket.readyState;
  }

  send(message)
  {
    if (this.webSocket.readyState == WebSocket.OPEN)
    {
      this.webSocket.send(message);
    }
    else
    {
      console.error('webSocket is not open. readyState=' + this.webSocket.readyState);
    }
  }

  disconnect()
  {
    if (this.webSocket.readyState == WebSocket.OPEN)
    {
      this.webSocket.close();
    }
    else
    {
      console.error('webSocket is not open. readyState=' + this.webSocket.readyState);
    }
  }
}

There is no error message, and it looks like this :

enter image description here

Seems a lot of data was sent over to the browser, I can see from developer tool, which looks like this :

enter image description here

And if I un-comment the lines to draw a rectangle, it looks like this :

enter image description here

The image I generated on the server side looks like this :

enter image description here

So, what do I need to do to make the image show up in the html page ?

Frank :

Now I got it working, on the server side, the code looks like this :

for (String key : sMap.keySet())
{
  Session s = sMap.get(key);

  if (s.isOpen())
  {
    BufferedImage image = image_getter.getAnImage();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
//  ImageIO.write(image,"jpg",baos);
    ImageIO.write(image,"png",baos);
    byte[] byteArray = baos.toByteArray();
    s.getBasicRemote().sendObject(byteArray);       // Works on both Swing & browser client
  }
  else sMap.remove(key);
}

On the browser client side, javascript looks like this :

this.webSocket.onmessage = function (event)
{
  var msg = event.data;
  console.log('onmessage ::  ' + msg);                                   // [object Blob]

  var blobUrl = URL.createObjectURL(new Blob([msg]));
  var image = new Image();
  image.src = blobUrl;
// alert("blobUrl = "+blobUrl);                                           // blob:http://localhost:8080/cc3751d6-5b49-462d-8a6f-f2221c899abf
  image.onload = function() { context.drawImage(image, 0, 0); };
};

On Swing client side, java code looks like this :

@OnWebSocketMessage
public void onMessage(InputStream is)
{
  try
  {
    if (imageLabel!=null)
    {
      BufferedImage img = ImageIO.read(is);
      imageLabel.setIcon(new ImageIcon(img));
    }
  }
  catch (Exception e)
  {
    e.printStackTrace();
  }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=30031&siteId=1