Base64 Image Conversion in Plasmic.

Attempting to convert Base64 image uploaded via AntDesign’s upload component, but I can’t get it to work.

Is there any way I can get images out of Plasmic’s file upload as blobs?

Failing that, I welcome any suggestions for modifying the component to alter the upload method.

Hi, how are you trying to ultimately use this image data? Are you trying to display it on the page?

Hi Yang.

Yes, trying to display it on the page but not directly. I need it to go to the relevant row on my supabase database first. That database then delivers the image to plasmic.

I would store the base64 encoded string as is in your database, so when the data is loaded back from the database it’s also as a base 64 encoded string. Then you can display it on the image element with a dynamic value on the image source with something like:

`data:image/png;base64,${currentItem.image}`

Hmmm that’s one solution, though ideally we’d like to be able to browse images in the database for other reasons and can’t do that if they’re a base64 string, nor can we apply size transformations so bandwidth may suffer

@yang

As far as I can tell, the ant design upload component in Plasmic is modified to convert uploads to Base64. Would you be able to point me in the direction for altering that?

Hi, a few things to clarify!

Since you are storing this in a database, there’s no way for you to directly reference the database data as an image url or as any URL, since it’s behind an SQL interface. If also you want to apply image optimization server side, then you’ll need to put this with an actual image hosting platform.

Here’s the code for the upload component, feel free to fork it

Note that if you are trying to relay this information as a string in json, you’ll need some kind of encoding like base 64.

If for any reason you want to translate this into a binary blob object, you can do so client side as well, you don’t have to fork the component, just using something like the code you had before.

I may have misexplained a few things but I’ll clarify @yang !

Since you are storing this in a database, there’s no way for you to directly reference the database data as an image url or as any URL, since it’s behind an SQL interface. If also you want to apply image optimization server side, then you’ll need to put this with an actual image hosting platform.

That’s not an issue. I’m using a Supabase backend as an SQL integration in Plasmic studio. I’m also using a bucket on Supabase for image storage. I have no problem applying transformations and dynamically displaying images via Supabase on Plasmic, my issue is getting images TO Supabase.


Note that if you are trying to relay this information as a string in json, you’ll need some kind of encoding like base 64. If for any reason you want to translate this into a binary blob object, you can do so client side as well, you don’t have to fork the component, just using something like the code you had before.

This is my entire issue, sadly. I’ve tried all sorts of methods and I’ve debugged it down to very minimal Base64 decoding (I can only upload images as blob or arraybuffer) but I’ve come to the conclusion that atob doesn’t work in Plasmic’s code editor though I’m most likely doing something wrong.

Conclusion…

A super simple ideal outcome for me would be to be able to convert the Base64 string into atob like the code I provided above, so if you can tell me an easy way to do this clientside I’ll be the happiest man in the world.

Oh! Can you try: globalThis.atob() and globalThis.Blob?

No luck.

Trying:

const base64String = SGVsbG8gV29ybGQh/*placeholder*/)'; // Base64 string
const binaryString = globalThis.atob(base64String.split(',')[1]); // Binary data string
const blob = new globalThis.Blob([binaryString], { type: 'image/png' }); // Create a BLOB object

Is there something wrong with what I’m doing?

EDIT: Yes, being an idiot. I’m adding redundant steps here.

Actually, I’m doing something wrong as this works:

const base64String = ‘SGVsbG8gV29ybGQh’; // This is “Hello World!” in Base64
const decodedString = globalThis.atob(base64String);

Ok, here’s the latest emergency…

The above works and returns Blob {} (I’m assuming that’s correct?)

image

But it won’t let me submit as it sees that as undefined.

image

It also doesn’t like the formatting of my code.

What’s the fix?


Nor does it work as an arraybuffer:

const base64String = $state.upload.files[0].contents;

// Convert the Base64 string to a decoded string
const decodedString = globalThis.atob(base64String);

const uint8Array = new globalThis.Uint8Array(decodedString.length);

for (let i = 0; i < decodedString.length; i++) {
    uint8Array[i] = decodedString.charCodeAt(i);
}

const arrayBuffer = uint8Array.buffer;

It works correctly and outputs ArrayBuffer {} but Plasmic says “undefined” isn’t valid json


Also tried in a function:

(function() {
    var base64String = $state.upload.files[0].contents;

    // Convert the Base64 string to a decoded string
    var decodedString = globalThis.atob(base64String);

    var uint8Array = new globalThis.Uint8Array(decodedString.length);

    for (let i = 0; i < decodedString.length; i++) {
        uint8Array[i] = decodedString.charCodeAt(i);
    }

    var arrayBuffer = uint8Array.buffer;

    return arrayBuffer;
})();

CONSOLE LOGS:

Error constructing evaluation function for code `async () => {
        const $steps = {};
        $steps["httpPost"] = true ? (() => {
          const actionArgs = {dataOp: __wrapUserFunction({"type":"InteractionArgLoc","actionName":"dataSourceOp","interactionUuid":"hz3yniLFfmVb","componentUuid":"GXpr8QTJglyj","argName":"dataOp"}, () => ({
      sourceId: "8RUH3W45WjF2MawpkTVchQ",
      opId: "af4db606-f4e2-4c81-bfbc-5cd916fdd37f",
      userArgs: {
        path: [( ($state.upload.files[0].name) )], body: [( ((function() {
    var base64String = $state.upload.files[0].contents;

    // Convert the Base64 string to a decoded string
    var decodedString = globalThis.atob(base64String);

    var uint8Array = new globalThis.Uint8Array(decodedString.length);

    for (let i = 0; i < decodedString.length; i++) {
        uint8Array[i] = decodedString.charCodeAt(i);
    }

    var arrayBuffer = uint8Array.buffer;

    return arrayBuffer;
})();) )]
      },
      cacheKey: null,
      invalidatedKeys: [],
      roleId: null,
    })),continueOnError: __wrapUserFunction({"type":"InteractionArgLoc","actionName":"dataSourceOp","interactionUuid":"hz3yniLFfmVb","componentUuid":"GXpr8QTJglyj","argName":"continueOnError"}, () => (true))};
          return __wrapUserFunction({"type":"InteractionLoc","actionName":"dataSourceOp","interactionUuid":"hz3yniLFfmVb","componentUuid":"GXpr8QTJglyj"}, () => ((async ({ dataOp, continueOnError }) => {
        try {
          const response = await executePlasmicDataOp(dataOp, { userAuthToken: dataSourcesCtx?.userAuthToken, user: dataSourcesCtx?.user });
          if(dataOp.invalidatedKeys && dataOp.invalidatedKeys.find((key) => key === "plasmic_refresh_all")) {
            await Promise.all(
  Array.from(cache.keys()).map(async (key) =>
    mutate(key)
  )
);
            return response;
          }
          if(dataOp.invalidatedKeys) {
            await Promise.all(
  dataOp.invalidatedKeys.map(
    async (invalidateKey) =>
      Promise.all(
        Array.from(cache.keys()).map(
          async (key) => {
            if (
              typeof key === "string" &&
              key.includes(`.$.${invalidateKey}.$.`)
            ) {
              return mutate(key);
            }
            return Promise.resolve();
          }
        )
      )
  )
);
          }
          return response;
        } catch(e) {
          if(!continueOnError) {
            throw(e);
          }
          return e;
        }
      })?.apply(null, [actionArgs])), actionArgs);
        })() : undefined;
            if (
              typeof $steps["httpPost"] === "object" &&
              typeof $steps["httpPost"].then === "function"
            ) {
              $steps["httpPost"] = await __wrapUserPromise({"type":"InteractionLoc","actionName":"dataSourceOp","interactionUuid":"hz3yniLFfmVb","componentUuid":"GXpr8QTJglyj"}, (($steps["httpPost"])));
            }
      }`:  SyntaxError: Unexpected token ';'

Ultimately all the data needs to sent over HTTP. There are a few ways to accomplish this - some forms use multi-part mime-type encodings, but these days APIs frequently use JSON (including the built-in Plasmic APIs).

You can’t directly represent binary blobs (like ArrayBuffer) in JSON, it always needs to be encoded in some string. base64 encoding is just the most common such encoding.