Optimize Images Prior to Cloudpage Upload

Discover a lightweight and effective solution to resize and compress images directly on CloudPages, reducing file sizes while maintaining quality. Perfect for enhancing performance in Salesforce Marketing Cloud projects.

Category:
Developer
reading time:
7 minutes

Introduction

SFMC Expert and fellow Marketing Champion Zuzanna Jarczynska has an amazing blog post on how to Create a CloudPages form with an image/file upload option. I’m sure that the information on that page has been used hundreds or thousands of times to make clients happy in the Salesforce Marketing Cloud ecosystem.

The Problem

The generally accepted best practice is to utilize Base64 encoding in order to upload image files via the page and then pass them through a REST API Call on a helper page. The problem lies in that Base64 encoding—file sizes grow significantly. Typically, I’d expect a file size jump of about 33%, but I was seeing an increase of over 200%. For instance, a 2.1MB file became 4.7MB using Base64 encoding through the CloudPage platform. This wasn’t an issue until the 5MB limit became a constraint. In my use case of uploading pictures of forms, many reasonable image files were simply too large, and high-resolution images were unnecessary.

Our Options

1. Try to get binary file imports to work (challenging rework).

2. Split the Base64 encoding up and try to join them back together later.

3. Inform clients that files must be less than 2.2MB.

4. Build an image resize/refactor engine into the CloudPage.

We opted for option 4, and it worked remarkably well!

The Code

function processAndCompressImage(file, formdata) {

 const MAX_WIDTH = 1024; // Maximum width for the resized image

 const MAX_HEIGHT = 1024; // Maximum height for the resized image

 const QUALITY = 0.8; // Compression quality (0 to 1)

 const reader = new FileReader();

 reader.onload = function (event) {

   const img = new Image();

   img.onload = function () {

     const canvas = document.createElement("canvas");

     const ctx = canvas.getContext("2d");

     let width = img.width;

     let height = img.height;

     if (width > MAX_WIDTH || height > MAX_HEIGHT) {

       if (width > height) {

         height *= MAX_WIDTH / width;

         width = MAX_WIDTH;

       } else {

         width *= MAX_HEIGHT / height;

         height = MAX_HEIGHT;

       }

     }

     canvas.width = width;

     canvas.height = height;

     ctx.drawImage(img, 0, 0, width, height);

     const compressedBase64 = canvas

       .toDataURL("image/jpeg", QUALITY)

       .split(",")[1];

     uploadFileToServer(compressedBase64, file.name.split(".")[0], "jpeg", formdata);

   };

   img.onerror = function () {

     showNotification("Error processing the image. Please try again.", "error");

   };

   img.src = event.target.result;

 };

 reader.onerror = function () {

   showNotification("Error reading the file. Please try again.", "error");

 };

 reader.readAsDataURL(file);

}

How It Works:

1. Read the File: The function uses the FileReader API to load the selected file as a Base64 string.

2. Load the Image: The Base64 data is assigned to an <img> element. The onload event ensures the image is fully loaded before processing.

3. Resize the Image:

• New dimensions are calculated while maintaining the aspect ratio.

• If the image exceeds MAX_WIDTH or MAX_HEIGHT, dimensions are scaled down proportionally.

4. Compress the Image:

• A <canvas> element is used to draw the resized image.

• The toDataURL method converts the canvas content to a compressed Base64 string.

5. Upload the File:

• The compressed image is uploaded using a separate function, uploadFileToServer.

Key Parameters You Can Adjust

MAX_WIDTH and MAX_HEIGHT: Define the maximum dimensions of the resized image.

QUALITY: Controls the compression level. A value closer to 1 means better quality but larger file size.

Final Thoughts

Resizing and compressing images before upload can significantly enhance your application’s performance and user experience. The processAndCompressImage function offers a lightweight and effective solution. For advanced processing, consider libraries like Pica.js or server-side tools.

Feel free to tweak the parameters and use this code in your projects. Let me know if you have any questions or enhancements!

Aaron Beatty
CEO, Engage Evolution

REad more

all posts
Arrow – Consulthink Webflow Template
No items found.