Search code examples
javascripthtmlxmlhttprequestarraybuffer

Binary asset accessible from Javascript, without going through XMLHttpRequest


I would like to access an arbitrary binary file from JavaScript. I've found documentation which recommends going via XMLHttpRequest, an array buffer, and Uint8Array, like this:

var req = new XMLHttpRequest();
req.open("GET", "file.img", true);
req.responseType = "arraybuffer";

req.onload = function () {
    var arrayBuffer = req.response;
    if (arrayBuffer) {
        var bytes = new Uint8Array(arrayBuffer);
        // use bytes for the remainder of the program
    }
}
req.send(null);

However, I would like to access file.img without going through XMLHttpRequest, for two reasons:

  • I would like it to work fully locally, i.e. if both the page and file.img are accessed via file: URIs
  • The asynchronous nature of XMLHttpRequest.send/XMLHttpRequest.onload is a needless complication for my case, since file.img is <100k in size.

So all in all, I am looking for a way to include this binary asset file.img somehow in my page in the same way as one would include, for example, an image with a synchronous img tag.


Solution

  • I ended up storing the binary asset in a base64-encoded JavaScript string literal, importing that using <script src=...>, and accessing it using base64-js.

    I convert, ahead of time, the binary data into a JavaScript file with the following Make rule:

    %.img.js: %.img
        (echo "var image64 = \"\\"; \
        base64 $< | sed -e 's/$$/\\/'; \
        echo '";') > $@
    

    The sed line is needed to add \ to the end of each line to make it into a single string.

    Then, accessing it from JavaScript is a simple matter of using base64-js since it already has a function that decodes base64-encoded strings into an Uint8Array:

    <script src="js/base64js/base64js-1.3.0.min.js"></script>
    <script src="mydata.img.js"></script>
    
    var imageArray = base64js.toByteArray(image64);