Search code examples
pythondjangowebsocketdjango-channels

Websocket Send and Receive Image with Base64 bandwith problem


I coded a web socket using Django channels and now want to add the possibility to send images over the chat (obviously it is a chat application).

What I did for now:

  • The user picks an image (frontend)
  • The user sends it to the backend (HTTP POST)
  • I use Django signals (it is a listener for the database) to detect if there is a new message with an image appended
  • I send the image back over the websocket

Following is the problem:

  • It is slow (not too noticeable but quite slow)
  • Sometimes it causes weird misbehavior

So now I thought about sending the image as a base64 and then sending it back directly so I never have any HTTP which can be helpful, because it is a little bit faster.
BUT: Base64 images are 20-30 percent bigger and I need to extract all the exif data in the frontend. Is there any possibility to send the images as a file over the websocket to the backend or if not is there a way to get around the quite greater size (20-30 percent), which is a problem because I cannot use too much bandwidth :/

How do other chat application solve this problem?


Solution

  • WebSocket.send() accept different data-types as parameter. You can transfer binary data over a WebSocket in both directions.

    On this snippet you can see how to make use of it on the client- and server-side in JavaScript. The Django channels also support binary data.

    You can attach any information to the binary data from the file and send it together with the file as a header.

    For example, by using 2 (or 3) Byte to indicate the length of the header. Which means, up to 64KB (or up to 16MB) for informations like filename and other infos you might need. In the end, this is similar to a HTTP POST.

    The message you send would then look like this:

     len of header     | header                 | file 
    -------------------+------------------------+-----------
     00 00 up to FF FF | infos about the upload | binary
    

    Even multiple files would be possible:

    < header len >
    < header >
    < file len >
    < file >
    < header len file 2 >
    < header file 2 >
    < file 2 len >
    < file 2 >
    ...and so on
    

    All you have to do on the serverside afterwards is to split the combined message back into it's parts defined by the length values.