Explain Codes LogoExplain Codes Logo

How to save a PNG image server-side, from a base64 data URI

javascript
base64
image-processing
file-system
Nikita BarsukovbyNikita Barsukov·Feb 20, 2025
TLDR

Let's cut to the chase! To quickly save a base64-encoded PNG to a file on your server using Node.js, do this:

/* You gotta have fs */ const fs = require('fs'); /* Regex: The pattern-seeking missile strikes again! */ const base64Data = YOUR_BASE64_DATA.replace(/^data:image\/png;base64,/, ""); fs.writeFileSync('output.png', Buffer.from(base64Data, 'base64'));

Replace YOUR_BASE64_DATA with your actual data URI. Make sure to remove the MIME type. This will write your PNG file to 'output.png' in a snap!

The Prep: Base64 data sanitization and validation

Kick-starting the process might seem like a walk in the park, but don't forget the importance of keeping your code safeguarded and prepared in the right way.

Preparing and sanitizing your base64 data

Before using the base64 data, it's highly advised to sanitize and validate it to repel potential security issues. That's where the mighty preg_replace comes to your rescue.

const cleanBase64 = base64Data.replace(/^data:image\/\w+;base64,/, ''); // Regex: Banishing evil spirits from your base64 data

Keeping base64 data intact

Accidental spaces in your base64 string might trip up the decoding process. Play safe by replacing spaces with pluses:

const preparedData = cleanBase64.replace(/\s/g, '+'); // No room for traffic here, keep moving!

Performing permissions check

Keep an eye on the directory permissions where you plan to save the file.

if (!fs.existsSync('path/to/your/dir')) { fs.mkdirSync('path/to/your/dir', { recursive: true }); } // Keeps the 'Permission denied' monsters away!

Writing the binary image

fs.writeFile('path/to/your/dir/output.png', Buffer.from(preparedData, 'base64'), (error) => {
  if (error) throw new Error('Failed to write the file:', error);
  console.log('File saved successfully.');
});
// Place your assumptions in the wreck file!

A meaningful and unique file name can protect your existing files from accidental overwrite. So, gear up and consider utilizing uniqid to generate unique file names.

Error handling

Never let errors off the hook. If decoding fails, handle it gracefully and prevent your application from crashing. It speaks volumes about your understanding and handling of potential issues.

Digging deeper with Image manipulation

const image = Buffer.from(preparedData, 'base64');
// It's like a photo bowl. Ready for some exotic toppings!

How about some resizing, cropping or filters before saving the image? You can accomplish this by using image processing libraries like Sharp.

Dealing with different scenarios

Supporting multiple formats

Have multiple image types to deal with? Be always prepared by including the correct extension.

// The matchmaker pairs up the MIME type and extension const matches = base64Data.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/); if (matches && matches.length === 3) { const extension = matches[1].split('/')[1].toLowerCase(); // Added flexibility of handling various image types }

Validating for success

No one likes broken stuff! So, validate base64 data before the decoding process for a smooth run.

const isBase64 = (str) => { return str.match(/^[A-Za-z0-9+/]*={0,2}$/); }; if (!isBase64(preparedData)) { throw new Error('Invalid base64 data'); } // The bouncer makes sure only valid base64 gets in!

Memory management

Consider using streams for reading and writing larger image data. Your system's memory will appreciate it!

const stream = fs.createWriteStream('output.png'); stream.on('finish', () => console.log('File saved successfully')); stream.write(Buffer.from(preparedData, 'base64')); stream.end(); // For memory’s sake, go with the flow....stream flow!

Don't forget about security

Remember the data sanitization mentioned earlier? Well, always sanitize any input, especially the ones interacting with your file system!