Module 3 · Preparing documents
Lesson 3.1
Format detection
Format detection reads the first bytes of a file to find its real type, instead of trusting the file name.
The problem
Why it matters
Without it
A file named "report.pdf" may really be plain text. The PDF reader then fails, or it returns garbled text.
With it
The first bytes name the real type. The file goes to the right reader, and a mismatch with its name is reported.
How it works
Files start with fixed bytes
Many file types start with a fixed pattern of bytes, called a signature. A byte is a number from 0 to 255, written here in hexadecimal. A PDF file starts with 25 50 44 46, which spells "%PDF" in text.
File First bytes (hex) Text they show manual.pdf 25 50 44 46 %PDF logo.png 89 50 4E 47 one non-text byte, then PNG report.pdf 52 65 66 75 Refu The first four bytes of three uploaded files. const head = Buffer.from("%PDF-1.7 fake body").subarray(0, 4);const hex = [...head].map((b) => b.toString(16).toUpperCase());console.log("Bytes ->", hex.join(" "));Output
Bytes -> 25 50 44 46
The first bytes are compared with known signatures
The program compares the first bytes of a file with a short list of known signatures. Only the first few bytes are read, so the check is fast. The PNG signature 89 50 4E 47 does not match the PDF signature, so the two files are told apart.
- First bytes
- Compare with known list
- Matching type
- Reader
The check runs on the first bytes only, not the whole file. const signatures = [ { type: "pdf", bytes: [0x25, 0x50, 0x44, 0x46] }, { type: "png", bytes: [0x89, 0x50, 0x4e, 0x47] },];const head = [0x89, 0x50, 0x4e, 0x47, 0x0d];const match = signatures.find((s) => s.bytes.every((b, i) => head[i] === b),);console.log("Type ->", match?.type ?? "unknown");Output
Type -> png
The name is only a label
The extension, such as ".pdf", is a label that anyone can set. For "report.pdf", the name says PDF, but the first bytes are plain text with no known signature. The name check then reports that the name and the content do not match. A matching signature does not prove the file is clean, so readers still handle errors.
File name
- report.pdf
- Name says: pdf
First bytes
- Plain text: "Refu"
- Detected: unknown
The name and the content of report.pdf disagree. const name = "report.pdf";const ext = name.split(".").pop();// The byte check found no signature for this file.const detected = "unknown";const note = detected === ext ? "match" : "no name match";console.log(ext, "vs", detected, note);Output
pdf vs unknown no name match
Unknown types are not guessed
A file with no known signature goes to a review list. The program does not guess its type, because a wrong guess can corrupt the text. Plain text has no signature, so it needs a separate check that this lesson skips. Each detected type goes to its own reader, so manual.pdf goes to the PDF reader.
- report.pdf
- No known signature
- Review list
The path for a file with no known signature.
Common mistakes
What goes wrong
- Trusting the extension alone. A renamed file then goes to the wrong reader.
- Reading the whole file to find its type. The first few bytes are enough.
- Guessing a type for unknown files. Set them aside and review them.
Use it when and skip it when
Is it the right tool?
Use it when
- Users upload files, and their names cannot be trusted.
- Your pipeline reads several formats, such as PDF and plain text.
Skip it when
- Every file comes from one tool that always writes the same format.
- You accept one format only, and a failed read is shown to the user anyway.
Words to know
Terms in this lesson
- Signature
- The fixed bytes at the start of a file that name its type.
- Extension
- The end of a file name, such as ".pdf", used as a label.
- Byte
- A number from 0 to 255, the basic unit of stored data.
- Reader
- A program that reads one file type and returns its text.