[SOLVED] How to upload Base64 images with the JavaScript SDK

Hi there,

I have the following Node function that uses the JavaScript SDK in order to upload images found in an HTML file:

// Utility function to find and upload any images in an HTML string
function processImagesInHTML(html) {
    // Find images that Ghost Upload supports
    let imageRegex = /="([^"]*?(?:\.jpg|\.jpeg|\.gif|\.png|\.svg|\.sgvz))"/gmi;
    let imagePromises = [];

    while((result = imageRegex.exec(html)) !== null) {
        let file = result[1];
            // Upload the image, using the original matched filename as a reference
            imagePromises.push(api.images.upload({
                ref: file,
                file: path.resolve(file)
            }));
    }

    return Promise
        .all(imagePromises)
        .then(images => {
            images.forEach(image => html = html.replace(image.ref, image.url));
            return html;
        });
}

I’ve been struggling to find an equivalent for Base64 images - I’ve tried using both Blobs and buffers but have not been able to construct a solution. Does anyone know how to modify this function to directly upload base64 images?

Thanks!

Hey there! Generally, you’d put the base64 image directly in the HTML. Otherwise, I think you’d want to convert it to an image format before uploading, especially because base64 images are significantly larger than typical file formats.

It’s possible, tho, that I’m overlooking your use case, so please elaborate if that’s so!

1 Like

Hey!
When I try to upload the HTML directly with the base64 images inline, the image never appears to upload when I go to the page in the Ghost web editor
image.

It sounds like just saving the files and then uploading may be the best approach then!

Probably. Uploading as an image has the benefit of being able to easily edit it later from the post editor.

However, you should be able to upload it in the HTML, too. I’d look at the HTML source and share what it looks like. I’m guessing that you’ll likely need to use the html card to ensure lossless conversion. See the docs on how to do that:

1 Like

Got it, thank you ryan!

Please never try to store base64 images in HTML cards :pray:

Images should always be converted to a typical image format and uploaded via the images endpoint to get a URL back for use in the content. If you do manage to save a base64 image directly in the post content you’re sending large amounts of binary data back and forth on every operation involving the post which is hugely inefficient, will result in performance problems, and quickly use up database space.

Back to the original question… do you know the data type for the images or do they already have the data type prepended to the base64 string?

If you know the datatype you can convert to a blob and upload, e.g.:

// your base64 data may already contain the `data:img/jpeg;base64,` part
const imgResponse = await fetch(`data:image/jpeg;base64,${base64Data}`);
const imgBlob = await imgResponse.blob();

const formData = new FormData()
formData.append(file, new File([imgBlob], 'imgFilename.jpeg');
formData.append('ref', 'imgFilename.jpeg');
formData.append('purpose', 'image');

const imgUrl = await api.images.upload(formData);
2 Likes

To clarify, my app is receiving HTML documents with images inline, and my goal was to upload those to Ghost.

The example code works for URL HTML images, but not inline base64 images, so I was wondering if there was a way to directly upload the base64 images to Ghost, rather than save them as a file, upload them to ghost, and then delete them!

I ended up doing just that, but I might switch the code over to your version since all the info is just stored in memory!

Thank you! I’ve really appreciated your help @Kevin

1 Like