React (TypeScript): Blob/File to base64 using FileReader.readAsDataURL()

This shows how to convert a Blob or File object to base64 string.
Conversion from a Blob to a base64 happens when a image is retrieved via an api, while conversion from a File to a base64 is for file uploading via form input.

For both cases, we can use FileReader.readAsDataURL() function.
Therefore, this time uses a common function for the converting.

Common function with FileReader.readAsDataURL()

This function is used in these 2 two cases:

  1. Conversion of File object inputed in <input type="file" />
  2. Conversion of image (Blob object) retreaved via an api
export const fileToBase64 = (file: File | Blob): Promise<string> =>
  new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
     resolve(reader.result as string);
    };

    reader.readAsDataURL(file);
    reader.onerror = reject;
  });

File to base64

Assume you want to preview multiple images inputed in <input type="file" />.
You have the following element.

<input type="file" multiple onChange={onSelectFiles} />
const onSelectFiles = async (e: React.ChangeEvent<HTMLInputElement>) => {
  const tempFileList: { fileName: string, base64String: string }[] = [];
  await Promise.all(
    [].map.call(e.target.files, async (file: File) => {
      tempFileList.push({
        fileName: file.name,
        base64String: file.type.indexOf('image') > -1 ? await fileToBase64(file) : '',
      });
    })
  );

  // Do something like updating the component state or redux state.
};

A File object is an array like object, but we cannnot use Array prototype functions like map(). So [].map.call() is used here.

That function picks only image files for the conversion by using file.type.indexOf('image') > -1.

If you allow single file for the <input>, you can just use this.

const onSelectFiles = async (e: React.ChangeEvent<HTMLInputElement>) => {
  const file = e.target.files[0];
  const tempFileList: { fileName: string, base64String: string } = {
    fileName: file.name,
    base64String: file.type.indexOf('image') > -1 ? await fileToBase64(file) : '',
  };

  // Do something like updating the component state or redux state.
};

Blob to base64

When you convert an api-fetched binary image data to base64, you might encounter the following error in the common function above.

TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'.

That is due to the responseType in the api request.
You need to set responseType: 'blob' like this. (This case uses axios for example.)

const base64String = await fileToBase64(
  (
    await axios.get(`${endpointUrl}`, {
      headers: {
        Accept: 'application/octet-stream',
      },
      responseType: 'blob',
    })
  ).data as Blob
)

That's it 👍👍👍