Adding Blurhash to image uploads

Hi everyone, based on Nikita_Ostryakov answer there’s a slightly easier way:

  1. We are leveraging https://plaiceholder.co to make our base64 (or any other type of placeholder type). To install this run npm install plaiceholder or yarn add plaiceholder

  2. Make a file inside the ./src/extensions folder named extendFileUpload.js. Put the following code inside the file (I chose to have a separate file for the extension to keep things clean):

// ./src/extensions/extendFileUpload.js
const plaiceholder = require('plaiceholder');
const _ = require('lodash');

module.exports = {
    generatePlaceholder(strapi) {
       
        // Here we are adding the attribute 'placeholder' to the file types
        strapi.contentType('plugin::upload.file').attributes.placeholder = {
            type: 'string',
        };

        strapi.plugin('upload').services.upload.uploadFileAndPersist =
            async function (fileData, { user } = {}) {
                const config = strapi.config.get('plugin.upload');

                const {
                    getDimensions,
                    generateThumbnail,
                    generateResponsiveFormats,
                } = strapi.plugin('upload').service('image-manipulation');

                await strapi.plugin('upload').provider.upload(fileData);

                const thumbnailFile = await generateThumbnail(fileData);

                if (thumbnailFile) {
                    await strapi
                        .plugin('upload')
                        .provider.upload(thumbnailFile);

                    // Here we are generating the placeholder based on the thumbnail buffer
                    try {
                        await plaiceholder
                            .getPlaiceholder(thumbnailFile.buffer)
                            .then(({ base64 }) => {

                                // We'll set the generated base64 string to your placeholder attribute
                                fileData.placeholder = base64;
                            });
                    } catch (error) {
                        console.log(error);
                        error;
                    }

                    delete thumbnailFile.buffer;
                    _.set(fileData, 'formats.thumbnail', thumbnailFile);
                }

                const formats = await generateResponsiveFormats(fileData);

                if (Array.isArray(formats) && formats.length > 0) {
                    for (const format of formats) {
                        if (!format) continue;

                        const { key, file } = format;

                        await strapi.plugin('upload').provider.upload(file);

                        delete file.buffer;

                        _.set(fileData, ['formats', key], file);
                    }
                }
                const { width, height } = await getDimensions(fileData.buffer);

                delete fileData.buffer;

                _.assign(fileData, {
                    provider: config.provider,
                    width,
                    height,
                });

                return this.add(fileData, { user });
            };
    },
};

  1. Open the ./src/index.js where you add the following:
// ./src/index.js
const extendFileUpload = require('./extensions/extendFileUpload');

register({ strapi }) {
    extendFileUpload.generatePlaceholder(strapi);
},
  1. Restart your strapi server.

  2. When you upload a new image, the placeholder will be generated as well. When you fetch your images a new attribute will be populated, namely the placeholder attribute.

  3. (bonus) If you are using Next.js, you can use the placeholder="blur" and blurDataURL={placeholder} attributes to make your image utilise the placeholder we just created.

Cheers!

1 Like