Explain Codes LogoExplain Codes Logo

Creating a Blob from a base64 string in JavaScript

javascript
blob
base64
fetch-api
Nikita BarsukovbyNikita BarsukovΒ·Sep 20, 2024
⚑TLDR

Let's decode a base64 string to binary (byte array) using atob(), and encapsulate this binary data within Blob. Here we go:

let b64Data = 'base64String'; // rock and roll music in base64, why not? πŸ˜„ let contentType = 'yourContentType'; // e.g., 'image/png' let byteCharacters = atob(b64Data); let byteArrays = []; for (let offset = 0; offset < byteCharacters.length; offset += 512) { let slice = byteCharacters.slice(offset, offset + 512); byteArrays.push(new Uint8Array([...slice].map(char => char.charCodeAt(0)))); } let blob = new Blob(byteArrays, {type: contentType});

Notice how we've taken small slices of data to build our byte array - this greatly enhances performance. πŸš€

Handling Large Data: Tips and Tricks

Meet the mighty fetch API

The fetch API comes to the rescue when working with large base64 strings. It returns a Promise that resolves to the response to the request, whether it is successful or not.

let b64Data = 'yourSuperLargeBase64Data'; // perhaps the script for the next Avengers movie? πŸ¦Έβ€β™‚οΈ let contentType = 'yourContentType'; // whatever is appropriate fetch(`data:${contentType};base64,${b64Data}`) .then(res => res.blob()) .then(blob => { // Now go and save the world (or at least your Blob)! });

The special b64toBlob function

TSaving the day one too many times? Establish an utility function, b64toBlob:

function b64toBlob(b64Data, contentType = '', sliceSize = 512) { let byteCharacters = atob(b64Data); let byteArrays = []; for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { const slice = byteCharacters.slice(offset, offset + sliceSize); const byteNumbers = slice.split('').map(char => char.charCodeAt(0)); const byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } return new Blob(byteArrays, {type: contentType}); }

Now you're the star of code 'reuse'! 🌟

Canvas toBlob

When dealing with large images, the method canvas.toBlob outperforms canvas.toDataURL in terms of speed and memory usage.

let canvas = document.createElement('canvas'); // Didn't you always dream of drawing on a virtual canvas? canvas.toBlob(blob => { // You've just created your first work of art! πŸ–ΌοΈ Well, eventually. }, 'image/png');

When It's Not Only About base64: Additional Caveats and Considerations

FormData is your friend

When it comes to file uploads, you'd want to embrace FormData. It allows to work with binary data without needing base64 encoding:

let formData = new FormData(); formData.append('file', blob, 'filename');

You've just learned to manipulate files like a pro! πŸ“„βœ‚οΈ

Blob URL: creating and revoking

The URL.createObjectURL() method comes with a responsibility: always revoke Blob URLs when you're done.

let blobUrl = URL.createObjectURL(blob); let downloadLink = document.createElement('a'); downloadLink.href = blobUrl; downloadLink.download = 'filename'; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); URL.revokeObjectURL(blobUrl);

Clean code, clean memory, happy life! 🧹

UI block avoidance

Make your UI responsive even when processing large files. A superhero comes prepared with weapons like Web Workers or Async/Await. That's how they roll! πŸŒ€

Code Optimizations for Robustness and Efficiency

Content type matters

Always specify the correct contentType when creating a Blob

let blob = new Blob([myData], {type: 'data/toTheMoon'});

Browser compatibility

Consider checking browser compatibility for the fetch API and Blob handling methods. You'd want your superpowers to work everywhere, won't you?