Search code examples
javascriptjavajquerybase64restlet

How to send (encode) a PNG image using Restlet and receive (decode) it using jQuery?


I have an image on my Restlet server. I want to transmit it to the client to display it in the FabricJS canvas.

On the server, first, I read the image:

import org.apache.commons.io.FileUtils;

private byte[] readImage() {
    try {
        return FileUtils.readFileToByteArray(
                new File(Utils.composeMapImagePath([...])));
    } catch (final IOException exception) {
        getLogger().severe(exception.getMessage());
    }
    return new byte[0];
}

Then, I read the byte array and encode it using Base64.

@Get
public String getImage() {
    [...]
    byte[] data = readImage();
    return Base64.encode(data, false);
}

On the client I receive a text in $xhr.responseText, which starts with

iVBORw0KGgoAAAANSUhEUgAADMgAABSACAYAAADX2AyFAACAAElEQVR42uzcXW7cuLYGUA+93jKMnkYm0MAdRCNTqYscJN2xDFtSiaT2zzoL38tBI7GrKIrc5M7b29vzGSpAHtHmD/MZkHV+AsD7wvrY+Kn2eRrznj8AAEjq8Xh8GZ+QepL9n89bRL0FvE/MTwAAkdd/FmiADaT5DMxP5gsA7wvxvss1fnw+

Then, I try to convert the string into PNG image using code like

var img = document.createElement("IMG");
img.onload = function(){
   var fImg = new fabric.Image(img, {options});
   canvas.add(fImg);
   canvas.renderAll();
    canvas.setBackgroundImage(img, function() {
        canvas.renderAll();
    });
}
img.src = myDataURL;

where myDataURL is constructed using one of the following methods:

  • var myDataURL = "data:image/png;base64," + btoa($xhr.responseText);
  • var myDataURL = "data:image/png;base64," + btoa(unescape(encodeURIComponent($xhr.responseText)));

Something goes wrong because the image is not displayed in the canvas, and Chrome doesn't display it in the preview:

Screenshot

enter image description here

I can change both client and the server.

How should I encode and decode the image in order for it to be displayed correctly?


Solution

  • It seems that your problem comes from the media type of your response.

    I made a test with jQuery and I made things work by updating the server resource as below:

    @Get
    public String getImage() {
        [...]
        byte[] data = readImage();
        return new StringRepresentation(
            Base64.encode(data, false),
            MediaType.TEXT_PLAIN);
    }
    

    On the client side, I used this code:

    <html>
      <head>
        <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
        <script type="text/javascript">
        function test() {
          $.ajax({
            url: "/image"
          })
          .success(function( data ) {
            var canvas = document.getElementById('canvas');
            var context = canvas.getContext('2d');
            var img = new Image();
    
            img.onload = function() {
              context.drawImage(this, 0, 0, canvas.width, canvas.height);
            }
    
            img.src = "data:image/gif;base64," + data;
          });
        }
    
        $(document).ready(function() {
          $('#test').click(function() {
            test();
          });
        });
        </script>
      </head>
      <body>
        <div id="test">Test</div>
        <canvas id="canvas" width="50" height="50"></canvas>
      </body>
    </html>
    

    Hope it helps you, Thierry