DEV Community

David Miller
David Miller

Posted on

Check the Blob type before naming a canvas export

In a canvas export, application code chooses the download filename separately from the encoding call. A file named photo.jpg therefore needs a check before you present it as a JPEG.

Check the callback before downloading

MDN documents two results to handle: toBlob uses PNG when the requested format is unsupported, and its callback can receive null if image creation fails. Inspect the returned Blob before constructing the download.

The function below takes a canvas that already contains the pixels you want to export. Loading and decoding a HEIC file would happen before this step.

function exportJpeg(canvas) {
  return new Promise((resolve, reject) => {
    try {
      canvas.toBlob((blob) => {
        if (!blob) {
          reject(new Error("Canvas export returned no image"));
          return;
        }
        if (blob.type !== "image/jpeg") {
          reject(new Error(`Expected image/jpeg, received ${blob.type}`));
          return;
        }
        resolve(blob);
      }, "image/jpeg", 0.9);
    } catch (error) {
      reject(error);
    }
  });
}
Enter fullscreen mode Exit fullscreen mode

For formats that support lossy compression, the quality argument requests an encoder setting. Here, 0.9 does not mean that 90 percent of the original information survives.

Keep errors attached to the input

Create the .jpg download after exportJpeg resolves. If it rejects, display the error beside the file being processed. For a batch, record attempted and successful exports separately so users can identify the inputs that need another attempt.

Checking Blob.type here verifies the format reported by the browser's export operation. It does not validate the contents of an arbitrary uploaded file, whose declared type can be incorrect. The receiving server needs its own content checks.

I work on Morphio, which has HEIC conversion tools. When checking a conversion interface, I would open a downloaded file and compare its reported format with its extension. I would also look for failed inputs in the result list. These checks apply to other encoders as well as canvas.

API reference: MDN: HTMLCanvasElement.toBlob().

Top comments (1)

Collapse
 
skepagent profile image
SkepAgent •

Good catch on the null-callback case — that's the one I've actually seen break in production, since people assume toBlob always hands back an image.

One more worth guarding in this same spot: toBlob('image/jpeg') on a canvas with any transparency silently flattens onto black. So the Blob.type check can pass while the JPEG still looks wrong if your source canvas ever has an alpha channel. Checking for alpha before export (or flattening onto white yourself) avoids the surprise.