runlocally

runlocally engineering notes

ZIP Viewer

How ZIP Viewer is built

By Geppetto · · Open ZIP Viewer →

These are the engineering notes for ZIP Viewer: the technologies it is built on, what each one is, and how it is used in the tool.

Tech used

Reading a ZIP without extracting it

The ZIP central directory (introduced in the Create ZIP notes) is what makes this possible: because it lists every entry’s name, size, timestamp, and flags at the end of the file, you can show an archive’s full contents without decompressing a single byte. That is the whole design — this is a lister, not an extractor.

@zip.js/zip.js: ZipReader and getEntries

The archive is opened with a ZipReader over a BlobReader(file), and reader.getEntries() parses just the central directory and returns the entry list. The call that would decompress an entry’s data — getData() — is never invoked. Each entry yields its name, compressed and uncompressed size, timestamp, an encrypted flag, and the filenameUTF8 flag.

The UTF-8 filename flag

Each entry carries the UTF-8 language-encoding flag (general-purpose bit 11, from the Create ZIP notes). When it is off and the name contains high bytes, that name was probably written in a legacy code page and may render as mojibake. The viewer flags those rows rather than guessing at a re-decode, and points at the Fix ZIP Filenames tool.

Shell

Same static Astro + Preact island and Service-Worker PWA shell as the other tools (see the HEIC notes). The listing runs on the main thread — there is nothing to decompress, so no Web Worker is needed.

Implementation & operational notes

Lazy, so it scales. Only the trailing directory is read, so listing stays fast and memory-light even for large archives; the ceiling is device memory, not a fixed limit.

Encrypted archives still list. The central directory isn’t encrypted — only the entry data is — so names, sizes, and a 🔒 marker appear even for password-protected zips. The contents are never read or decrypted.

It deliberately does nothing else. No per-entry extraction, no content preview, no download. Surfacing the entry list honestly — including flagging probable mojibake — is the entire job.

Try it / source