Memory-Safe Media Preflight in Mobile Browsers
Client-side media preflight can improve an upload experience, but it can also crash the page before the network request begins. A twelve-megapixel JPEG may be only four megabytes on disk and tens of megabytes after decoding. Creating several full-size canvases at once is enough to exhaust memory on older phones. Preflight is policy, not editing Decide what the browser must prove before transfer. Useful checks include file count, compressed byte size, declared type, readable dimensions, and a conservative duration limit for video. Avoid mandatory re-encoding unless the product truly needs it. Every transformation adds CPU time, memory pressure, battery use, and another failure mode. Process one file at a time A file picker may return twenty items. Do not decode all of them to build previews. Maintain a queue with one active decode on constrained devices and at most two on stronger ones. for ( const file of files ) { const result = await inspect ( file ); renderResult ( result ); await yieldToMainThread (); } The UI can list filenames immediately while dimensions and thumbnails arrive progressively. Prefer metadata over full pixels Use createImageBitmap with resize hints when supported. It can decode away from the main rendering path and avoid a full-resolution canvas for a small preview. const bitmap = await createImageBitmap ( file , { resizeWidth : 640 , resizeQuality : ' medium ' }); Always close bitmaps after drawing. Revoke object URLs when the component unmounts. Small leaks become large when guests select and remove files repeatedly. Handle orientation and color carefully Modern browsers generally honor EXIF orientation when decoding, but behavior differs across APIs and older engines. Test portrait photographs from real iOS and Android devices. Do not strip metadata silently if the original is supposed to remain untouched; upload the source file and treat the preview as disposable UI. Color differences between the preview and exported original are usually les