Search code examples
javascriptjavawebsocketbufferedimagejava-websocket

websocket api - image encoding yields no image type on client side


I have a web socket server on tomcat 8 with the following binary use:

sess.getBasicRemote().sendBinary(bf);

where bf is a simple image to bytes conversion as follows:

BufferedImage img = ImageIO.read(...);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write( img, "png", baos );
ByteBuffer bf = ByteBuffer.wrap(baos.toByteArray());

this code ends up in the the client side (javascript) as a blob and eventually rendered as an image in the browser and this seems to work just fine. the only thing that's strange is the the image is rendered typeless as:
data:;base64,iVBORw0KGgoAAAA......== without the type (image/png).
if I use online encoders for the same image I will get:
data:image/png;base64,iVBORw0KGgoAAAA......== (notice the image/png type)

and so my question is why is that? is my image to byte conversion wrong? like I said, the image is displayed fine it just is missing the type. Note that the data send from the java websocket server is not encoded with base 64, its something I do on the client side (via JS's FileReader.readAsDataURL(blob) - very common).

thanks a lot and sorry for the long post


Solution

  • No, your image to byte array conversion is not wrong. Byte array conversion treats the images as a binary stream, it has nothing to do with the MediaType contained in it.

    The type that you want to see is a Data URI media type. Normal java code for converting files to byte array won't give you data URL scheme compliant URL.

    From the RFC

    data:[<mediatype>][;base64],

    The <mediatype> is an Internet media type specification (with optional parameters.) The appearance of ";base64" means that the data is encoded as base64. Without ";base64", the data (as a sequence of octets) is represented using ASCII encoding for octets inside the range of safe URL characters and using the standard %xx hex encoding of URLs for octets outside that range. If <mediatype> is omitted, it defaults to text/plain;charset=US-ASCII. As a shorthand, "text/plain" can be omitted but the charset parameter supplied.

    RFC source

    When you're creating the Blob object in Javascript you have an option to pass MediaType to it so that when you read it using FileReader.readAsDataURL it fills the appropriate media type.

    Example is below

    var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } );
    

    Source

    You probably don't need BufferedImage in your code, simple file read should suffice.

    Following is equivalent of your code with Apache FileUtils.

    ByteBuffer bf = ByteBuffer.wrap(FileUtils.readFileToByteArray('test.jpg'));