It is often handy to create downloadable content on the fly using JavaScript. Sometimes you may want to do so while also encoding the contents as base64. That is where the btoa() function comes in handy. Here is an example of doing just that:

let content = 'Hello JS world!!!';
Object.assign(document.createElement('a'), {
  href: 'data:text/plain;charset=utf-8;base64,' + btoa(content),
  download: 'example-' + (+new Date()) + '.txt'
}).click();

As you can see by clicking here, the above code does in fact make it possible to download an example text file with the message “Hello JS world!!!”.

I’m Getting An Outside of Latin1 Range Error!

If you are getting this error you are undoubtedly trying to use this same method with special characters that are outside of the \u0000 to \u00ff. The following is an example of code that will not work using the same method as outlined above:

let content = 'Hello JS world!!!  This has been a very interesting\u2026';
Object.assign(document.createElement('a'), {
  href: 'data:text/plain;charset=utf-8;base64,' + btoa(content),
  download: 'example-' + (+new Date()) + '.txt'
}).click();

By clicking here you will see the error that is produced when trying to run the above code. In order to get this code to work correctly you can turn all of the characters into a Latin1 range string that when interpreted as UTF-8 will still produce the expected result. The 2 functions that you can use together are encodeURIComponent() followed by unescape(). Here is the working code:

let content = 'Hello JS world!!!  This has been a very interesting\u2026';
Object.assign(document.createElement('a'), {
  href: 'data:text/plain;charset=utf-8;base64,' + btoa(unescape(encodeURIComponent(content))),
  download: 'example-' + (+new Date()) + '.txt'
}).click();

Click here if you want to see if this really works.

Final Words

I have found that simply making the data URL without base64 seems to be easiest option:

let content = 'Hello JS world!!!  This has been a very interesting\u2026';
Object.assign(document.createElement('a'), {
  href: 'data:text/plain;charset=utf-8,' + encodeURIComponent(content),
  download: 'example-' + (+new Date()) + '.txt'
}).click();

Click here to see the above code in action. As you can see we only need to use the encodeURIComponent() function in the case that we are not specifying base64 encoding of the data URL. For this reason it seems that the best option is to simply encode the contents once without having to use base64 (via btoa()) at all.

Let me know what you think and what you have found has worked and/or has not worked. As all always, happy coding!!! šŸ˜Ž

Categories: BlogJavaScript

Leave a Reply

Your email address will not be published. Required fields are marked *