File & PDF Tools

Create ZIP Archive

Package multiple files into a ZIP archive in the browser.

Create ZIP archive
Package multiple files into a standard ZIP archive.
Local processing

Create ZIP Archive

Package multiple files into a standard ZIP in your browser with compression levels from 0 to 9.

Output

  • Duplicate names receive a numeric suffix
  • Total input is limited to 250 MB
  • Higher levels may be slower and do not shrink every file type

Packs several local files into one standard ZIP archive entirely inside the browser, with a DEFLATE level from 0 to 9 and automatic renaming of colliding file names. Suited to handing over a batch of logs, source files or small text exports as a single download without uploading anything.

What is actually inside the archive

The output is a byte stream of three parts: for every entry a 30-byte local file header followed by the 9-byte name and the payload, then one central directory holding a 46-byte record per entry, then a 22-byte end-of-central-directory record signed 50 4B 05 06. Because each name is written twice, a single notes.txt costs 116 bytes of scaffolding no matter how tiny the file is. Measured: 11,000 bytes of DevToolbox plus a trailing space repeated 1,000 times pack to 170 bytes at level 6, while level 0 yields 11,116 bytes — the payload plus exactly that 116-byte overhead. Compression only rewrites the data area; headers and names stay literal.

What the 0–9 slider really changes

Entries are compressed with the DEFLATE format of RFC 1951, and the method field of each header records which path was taken: 8 means a raw DEFLATE stream, 0 means the bytes were stored verbatim. Level 0 here takes the stored path, so it is fast and the archive is the input plus headers. Levels 1–9 only govern how hard the matcher hunts for repeated substrings: on the repetitive test file levels 1, 6 and 9 all produced the same 54-byte entry, while 64 KiB of random bytes defeated deflate entirely and grew to 65,551 bytes against 65,536 when stored — a 15-byte loss pure block overhead. The slider starts at 6; only inputs with genuine redundancy repay higher settings.

Names, duplicates and the UTF-8 flag

Entries are keyed by name in a plain object before writing, so two files called report.txt would collide and the second would silently overwrite the first instead of raising an error. This tool therefore renames repeats to report-2.txt and report-3.txt before packing. Names are written as UTF-8, and any non-ASCII byte sets bit 11 of the general purpose flag (0x0800); 报告.txt occupies 10 bytes and raises it, which is exactly what older extractors that ignore the bit get wrong. Modification times are stamped when you press Create, stored as MS-DOS date-time with 2-second resolution limited to 1980–2099, so repacking identical files gives different bytes but the same content.

Worked example

Packing a repetitive text file at level 6

Input
notes.txt: the 11-byte string "DevToolbox " repeated 1,000 times (11,000 bytes), compression level 6
Output
archive.zip: 170 bytes total; entry CRC-32 0xADAF7CC9, compressed size 54, method 8 (deflate), uncompressed size 11000

The payload collapses into a few back-references, so 11,000 bytes become 54; the other 116 bytes are the 30-byte local header, the 46-byte central record — both carrying the 9-byte name — and the 22-byte end record. The same input at level 0 gives 11,116 bytes, and levels 1, 6 and 9 all give 170 bytes.

Limits and pitfalls

  • Total input is capped at 250 MB, checked when files are picked and again before packing; every byte is held in memory, so a near-limit batch can still exhaust a small tab.
  • Level 0 stores entries without deflating, and levels 1–9 can still enlarge already-compressed media such as JPEG or MP4 by a few bytes of block overhead.
  • Colliding names are rewritten with a -2, -3 suffix inside the archive; your originals are untouched and no directory tree is created beyond names the browser itself reports.
  • Each run always produces archive.zip, so a second run replaces the previous result and an existing archive is never reopened, appended to or re-signed.
  • Only classic 32-bit ZIP fields are written: no ZIP64 records, no password, no AES encryption — encrypted archives have to be produced elsewhere.

Related tools

When it goes wrong

I dragged the level slider from 6 up to 9 and the size shown in the result panel did not move at all.

CauseThe slider only writes the compressionLevel ref through v-model.number; the existing blob is discarded inside processArchive() and by adding or removing a file, but not by a level change. The panel keeps advertising the archive built with the previous level, and the download button still hands out that older blob.

FixPress Create ZIP again — the header line and the download switch to the freshly packed archive. Judge the level by the byte figure in that header, never by the slider position.

I picked a second batch of files and the first batch vanished from the list instead of being added to it.

CauseIn zip-create mode selectFiles() assigns files.value = selected, so every pick, drop or paste replaces the entire list rather than appending. Only the per-row trash button subtracts, and it subtracts one file at a time.

FixSelect the whole batch in one gesture — Cmd/Ctrl+A inside the folder, or drag the selection in a single drop — and download the current archive before you start the next selection, because the list never holds two batches at once.

One 180 MB disk image keeps getting refused while the small files next to it go through.

CauseBytes are read by readFileBytes(), which throws FILE_TOO_LARGE above MAX_FILE_SIZE = 104,857,600 bytes (100 MB) for a single file, while assertTotalSize() separately caps the batch at 262,144,000 bytes (250 MB). The per-file ceiling is only enforced when Create ZIP runs, so the file is accepted into the list and rejected later.

FixSplit anything over 104,857,600 bytes with split -b 100m before adding it, or keep it out of the archive — this tool has no spanning or ZIP64 path, so a bigger entry could not be written correctly anyway.

The archive builds fine, then this site's own ZIP extract tool answers that it may contain at most 2,000 entries.

Causezip-create caps nothing but total size, so an archive with 3,400 entries is written without complaint. The extract side is the strict one: inspectZip() reads the entry count from the end-of-central-directory record and throws above 2,000, also refusing any entry over 100 MB or 500 MB of total uncompressed content.

FixCut the batch into archives of 2,000 entries or fewer and extract them one by one, or open the oversized one in 7-Zip, Finder or unzip — the file itself is a standard ZIP that those tools read without any entry limit.

A duplicate dotfile ended up called -2.env, and a duplicate tarball became backup.tar-2.gz.

CauseuniqueName() treats everything after the last dot as the extension and everything before it as the stem. For .env the whole name is the extension, so the stem is empty and the counter lands in front of the dot; for two-part extensions the counter is inserted between them, never at the end.

FixIf a build script matches exact names, rename locally before packing. Otherwise accept the output: the suffix always sits before the final extension, so backup.tar-2.gz still opens as a gzip stream and -2.env keeps its dotfile nature.

One concrete scenario

285 rotated logs against a 250 MiB ceiling

An on-call rotation leaves 285 rotated logs, app-001.log through app-285.log, 900 KiB apiece. At 921,600 bytes each the selection totals 262,656,000 bytes and the dropzone refuses it on the spot: the ceiling is 250 MiB, 262,144,000 bytes, and you are 512,000 over. Remove one file and 284 logs sit at 261,734,400 bytes — inside the limit with 409,600 bytes to spare. They are plain text, so leave the level at its default 6. Forcing level 0 would produce an archive of exactly the input plus 76 + 2 × 11 = 98 bytes of headers per entry, 27,854 bytes on top of 261.7 MB of logs. Both runs emit archive.zip, so rename the first download before packing the second batch.

Frequently Asked Questions

How much difference do levels 0–9 make?
Level controls how hard the compressor searches for repetition: on text, 9 versus 6 usually saves 1–5% while taking up to twice as long; on already-compressed media, no level helps. Default to 6; reach for 9 with many small text files.
Why did zipping my photos barely shrink anything?
JPEG/PNG/MP4 are already compressed — their entropy is spent, and ZIP finds nothing more while wasting time. To actually shrink media, transcode (images to WebP, video at lower bitrate); do not re-zip.
Are there size limits when packing in the browser?
Nothing uploads, but memory bounds apply — keep total input around 250 MB; larger archives belong to system tools. The browser’s advantages are privacy (files never leave the machine) and consistent cross-platform behavior.

Content reviewed: