When iPhone Users Upload HEIC, Your Frontend Crashes: The Fix That Works
Any web app that accepts photo uploads from iPhone users will eventually receive an HEIC file, and without conversion it can white-screen the page and send users away. Handling it client-side cuts upload size, but because browser support is patchy and serverless builds fight C++ dependencies, the only reliable pattern is a client conversion with a server-side fallback.
A mini-program that let users upload ID photos for resumes worked in testing but white-screened on launch day. The culprit was HEIC, the default image format on iOS since version 11. HEIC uses HEVC/H.265 encoding and produces files roughly half the size of JPEG at equal quality, which is why Apple adopted it. But outside the Apple ecosystem support is thin: Chrome only partially supports it from late 2020 and then only when the operating system can decode HEVC, Firefox does not support it at all, and most backend image libraries ignore it. The upload flow used FileReader, an Image object, and Canvas, and the failure happened when the browser tried to load the HEIC into an Image object and fired onerror.
The author evaluated three approaches. Server-side conversion with Node's heic-convert works but pulls in libheif with C++ dependencies that compile fine in Docker yet become painful inside serverless functions like AWS Lambda. It also forces users to upload the original multi-megabyte HEIC first, lengthening the whole round-trip. Client-side conversion using the heic2any library runs WebAssembly in the browser, turning HEIC into a JPEG Blob before any upload. That saves bandwidth, but the decoder adds about 600KB (200KB gzipped), so the author lazy-loads it only when a file's type or extension indicates HEIC. The final production solution combines both: attempt client conversion, catch failures, and upload the original file for the server to convert as a fallback.
The author also notes that file type detection should not rely only on MIME type, since file.type can be empty; checking the extension and magic number is safer. HEIC has two MIME spellings, image/heic and image/heif, and both need handling. Client-side conversion can take 3-5 seconds for a 4000x3000 photo on mobile, so a loading indicator is necessary. For quick one-off conversions the author points to an in-browser online tool that never uploads files, useful for non-technical colleagues who capture product photos on iPhones.
HEIC support is not just a browser feature; it depends on operating-system-level HEVC decoding, so even a modern browser can refuse the format on an older OS, making client-side conversion a fragile bet.
The dual strategy treats a failed client conversion as an expected event, which is the right assumption for a consumer app where browser versions, OS updates, and WebAssembly availability vary widely.
Uploading an original HEIC first wastes both user bandwidth and server processing time, which is why a client-side conversion wins even at a 200KB decoder cost for normal users.
The author's checklist about checking magic numbers and both MIME spellings reflects how browser inconsistencies are the rule, not the exception, in file-upload code.