codinggames

How to create a JSON download link using HTML only

Written in May 9, 2021 - 🕒 2 min. read

This week I was working on my project Resume Builder and I wanted to be able to create a button that downloads a JSON without using JavaScript.

The only way I knew how to do that was by using URL.createObjectURL in a blob file, but that wouldn’t work for me, because this link would be inside a PDF file.

Then I did the first thing any millennial would do, I searched on Stack Overflow, but I couldn’t find anything… how is that even possible? Well anyway, with some trial and error I was able to do it by using Base 64.

Let’s say I want to create a download button that will download a JSON like { foo: 'bar' }, first we need to convert it to a Base 64 string, we can do that with the native btoa JavaScript function:

const json = { foo: 'bar' };
const jsonString = JSON.stringify(json);
const base64Json = btoa(jsonString); // eyJmb28iOiJiYXIifQ==

Ok now that I know what is the Base 64 value for the { foo: 'bar' } object, I can create an anchor element like the following:

<a href="data:application/json;base64,eyJmb28iOiJiYXIifQ==" download="object.json">download</a>

And that’s all. In my case, I just needed the code to be served as HTML, and since I’m using Gatsby, my actual code is a React element that will be SSR for my PDF file:

const DownloadJsonLink = ({
    children,
    json = {},
    name = 'object.json',
}) => {
    const href = useMemo(
        () => {
            if (typeof window !== 'undefined') {
                const base64Data = btoa(unescape(encodeURIComponent(JSON.stringify(json))));
                return `data:application/json;base64,${base64Data}`;
            }

            return '#';
        },
        [json]
    );

    return (
        <a
            href={href}
            download={name}
            target="_blank"
        >
            {children}
        </a>
    );
};

export default DownloadJsonLink;

I knew it was possible to do this to download an image, but I had never tried for other types of files.

It is amazing to still learn HTML things even after many years of experience, and I hope that someone else learns something new with this post. See you next time.

Tags:


Post a comment

Comments

Shmu on 5/17/21

I had to create something similar for my weightlifting web application, to allow exporting your progress. When the user clicks a button, I dynamically generate this kind of anchor tag, and click it. Obviously this uses JS though. https://github.com/SamuelNorbury/norbury-lifts/blob/master/src/web/utils/export.js