Модуль I · Тема 6, урок 1 із 2 · 120 хвилин
Мета. Побачити, що тип файлу задають не букви після крапки, а перші байти всередині. І навчитися визначати справжній тип будь-якого файлу. Навіть якщо його навмисно перейменували.
.docx як архів і показати, з яких файлів
він складений;Слова «сигнатура», magic number і «MIME-тип» поки нічого не означають — розберемо їх по черзі.
| Етап | Хв | Що робимо |
|---|---|---|
| Фокус із перейменуванням | 10 | Чому браузер не обманувся |
| Сигнатури й hex | 25 | Перші байти десяти форматів |
| Hex-детектив | 15 | Вісім файлів без імені — упізнаємо формат за байтами |
| Перерва | 10 | — |
| Офсети й контейнери | 15 | Чому MP4 і DOCX — окремий випадок |
| MIME і Content-Type | 20 | Як тип передається по мережі |
| Інструменти в терміналі | 15 | file, xxd, Format-Hex |
| Практика й підсумок | 10 | Розбір набору й detect.txt |
| Разом | 120 |
«Розширення = тип файлу». Це неправда, і сьогодні ти в цьому переконаєшся
Візьми будь-яку фотографію, перейменуй photo.png на
photo.jpg — і подивись на розмір файлу. Він не змінився. Жоден
байт усередині не поворухнувся. Змінився тільки напис в імені.
Ім'я файлу зберігається у файловій системі, поруч із файлом, а не всередині нього. Це підпис на коробці. Вміст коробки він не змінює.
Ти перейменував схема.png на схема.jpg, щоб
«зменшити вагу». Що змінилося всередині файлу?
Але тоді виникає питання. Ім'я нічого не означає — як браузер розуміє, що йому надіслали картинку, а не текст? Відповідь проста: кожен формат починається з упізнаваного підпису. Його називають сигнатурою файлу або magic number — «чарівним числом».
logo.png, перейменований на logo.pdf, друкарня
отримає не PDF, а зіпсоване ім'я. Конвертація змінює структуру всередині,
перейменування — лише напис зовні.Тобі надіслали котик.jpg, який не відкривається у «Фотографіях».
Ти запускаєш file --mime-type котик.jpg, і він каже
image/png. Що сталося і як полагодити?
Кілька байтів на початку, за якими формат упізнають однозначно
Файл — це послідовність байтів. Кожен байт — це число від 0 до 255.
Записувати його прийнято двома шістнадцятковими цифрами: 00,
0A, FF. Такий запис називають hex.
Автори форматів домовилися так. На самому початку файлу стоїть кілька байтів, які більше ніде не зустрічаються в такому порядку. Прочитав перші 4–8 байтів — і вже знаєш формат. Решту гігабайта читати не треба.
Кожен байт сигнатури PNG ловить свою поломку при передаванні файлу:
| Байт | Навіщо він там |
|---|---|
| 89 | число більше 127 — якщо канал зв'язку «обрізає» восьмий біт, байт зіпсується й це одразу помітно |
| 50 4E 47 | літери PNG — щоб формат упізнавала людина |
| 0D 0A | пара «повернення каретки + переведення рядка»: ловить передавання в текстовому режимі, яке псує кінці рядків |
| 1A | у DOS це «кінець файлу» — команда type зупиниться тут і не заллє екран сміттям |
| 0A | ще одне переведення рядка — ловить зворотне перетворення |
Це не випадковий набір: так написано в самій специфікації PNG. Формат захищається від тихого псування при пересиланні. Щоб зіпсований файл не прикинувся цілим.
Учити їх напам'ять не треба. Але саме ці формати трапляються щодня, і за тиждень практики ти впізнаватимеш їх з одного погляду. Колонка «Офсет» каже, з якого байта дивитися: нуль — від самого початку файлу.
| Формат | Байти (hex) | Офсет | Як текст |
|---|---|---|---|
| PNG | 89 50 4E 47 0D 0A 1A 0A | 0 | ·PNG···· |
| JPEG | FF D8 FF | 0 | — |
| GIF | 47 49 46 38 | 0 | GIF8 |
| 25 50 44 46 | 0 | ||
| ZIP (і DOCX, XLSX, ODT, EPUB, APK) | 50 4B 03 04 | 0 | PK·· |
| MP3 із тегом | 49 44 33 | 0 | ID3 |
| MP3 без тега | FF FB | 0 | — |
| WAV | 52 49 46 46 … 57 41 56 45 | 0 і 8 | RIFF…WAVE |
| MP4 | 66 74 79 70 | 4 | ftyp |
| ELF (програма Linux) | 7F 45 4C 46 | 0 | ·ELF |
MP3 без тега починається також із FF F3,
FF FA або FF F2. Спільне в них — перший байт
FF. Ним починається кожна порція звуку всередині MP3, а другий
байт уточнює версію формату — тому він і різний.
Однокласник надіслав звіт.jpg. Ти дивишся перші байти —
там 50 4B 03 04. Що це насправді?
Вісім файлів без імені. Усе, що ти бачиш, — перші 16 байтів
Нижче — початок справжнього файлу. Угорі номер байта (офсет), посередині сам байт у hex, знизу той самий байт як текст. Крапкою позначено байт, який не має друкованого символу.
Твоє завдання — упізнати формат. Після відповіді сигнатура підсвітиться зеленим, і ти побачиш, що саме тебе мало наштовхнути.
рядок 1 — офсет · рядок 2 — байт у hex · рядок 3 — той самий байт як текст
Що це за файл?
file і будь-який пристойний
переглядач зображень.Два файли починаються однаково: 52 49 46 46 (RIFF).
Один із них WAV, другий — WebP-картинка. Як їх розрізнити?
Формати-контейнери влаштовані інакше: сигнатура зсунута
Відкрий MP4 у hex-переглядачі — і на нульовому байті не буде нічого схожого
на підпис. Там стоятиме щось на кшталт 00 00 00 20. Це не помилка.
MP4 зібраний із боксів (їх також називають атомами). Кожен бокс
починається однаково. Спершу чотири байти — розмір боксу. Далі ще чотири —
його чотирилітерна назва. Перший бокс у файлі завжди ftyp —
«тип файлу». Отже, розмір з'їдає офсети 0–3, а літери ftyp
починаються з офсету 4.
file шукає підпис не лише
на початку файлу, а й у заздалегідь відомих місцях.Ти написав власний скрипт, який читає рівно перші 4 байти файлу й порівнює їх зі списком сигнатур. На всіх MP4 скрипт мовчить. Чому?
Відкрий будь-який .docx у hex-переглядачі: там буде
50 4B 03 04, тобто PK··. Це підпис ZIP. Літери
PK — ініціали Філа Каца, автора формату.
Сучасний офісний документ — це не один шматок даних. Це папка з файлами, запакована в архів. Текст лежить в одному XML, стилі в іншому, картинки окремими файлами. Це стандарт: OOXML для Microsoft Office, ODF для LibreOffice.
Перевірити це можна не відкриваючи Word. Команда unzip -l
друкує список того, що лежить в архіві. А хвостик | head -8 просить
показати тільки перші вісім рядків. Без нього список поїхав би на цілий екран,
бо файлів усередині документа десятки.
Ось із чого складається твій реферат. У word/document.xml
лежить сам текст, у word/styles.xml — оформлення,
а [Content_Types].xml перелічує, що взагалі є в архіві. Word просто
пакує ці файли разом і показує тобі як один документ.
Вивід ілюстративний — у твоєму файлі будуть інші розміри.
Незмінне тут інше: [Content_Types].xml і
word/document.xml є в кожному DOCX. В ODT замість них перший
запис завжди називається mimetype і містить рядок
application/vnd.oasis.opendocument.text.
.docx, перейменуй копію на .zip
і розпакуй звичайним архіватором. Ти побачиш усередині теку word/
з файлом document.xml — там і лежить твій текст. Оригінал при
цьому не чіпай.50 4B 03 04 DOCX неможливо відрізнити від
звичайного ZIP чи від EPUB. Формат уточнюють вміст архіву й розширення.
Тому file для DOCX часто відповідає обережно —
application/zip, а іноді точніше:
application/vnd.openxmlformats-officedocument.wordprocessingml.document.Ім'я файлу по мережі не передається. Передається тип
Досі ми дивилися у файл, який лежить у тебе на диску. Але той самий файл ще й їздить по мережі. У дорозі імені в нього немає взагалі — то за чим його впізнає браузер?
Коли браузер запитує файл, сервер відповідає заголовком
Content-Type. Саме він каже, що робити з тілом відповіді.
Значення записують у форматі тип/підтип: image/png,
text/html, application/json, audio/mpeg.
Це і є MIME-тип.
Content-Type.Звідси беруться дві щоденні дивини. Перша — про JSON. Якщо сервер віддав
application/json або text/plain, файл відкривається
в браузері як текст. А якщо application/octet-stream — браузер
його завантажує.
Друга: картинка не показується, хоча за адресою вона є. Майже завжди сервер
віддав її з типом text/plain. Так буває, коли файл лежить без
розширення й веб-сервер не зміг здогадатися.
| Файл | MIME-тип | Що робить браузер |
|---|---|---|
index.html | text/html | малює сторінку |
photo.png | image/png | показує зображення |
report.csv | text/csv | здебільшого пропонує завантажити |
manifest.json | application/json | показує як текст |
track.mp3 | audio/mpeg | вмикає вбудований плеєр |
archive.zip | application/zip | завантажує |
Подивись на report.csv у таблиці. Малювати таблиці браузер
не вміє, тому чесно віддає файл тобі на завантаження. А track.mp3
він відкриє прямо у вкладці — бо для audio/mpeg у нього є плеєр.
Зверни увагу: MP3 має тип audio/mpeg, а не
audio/mp3. MIME-типи не вигадують — їх реєструє організація IANA,
і в звіті треба писати саме зареєстровану назву.
Ти виклав на сервер manifest.json. У браузері він відкривається
нормально, а от чужий скрипт, який його читає, скаржиться на тип. Що треба
перевірити першим?
file називає формат, xxd і hexdump показують самі байти
Команда file має власну базу сигнатур (її називають
magic). Вона читає початок файлу, шукає збіг у базі й повертає назву
формату. Ім'я файлу вона при цьому не враховує взагалі.
file відповідають на
різні запитання. Перший — «як цей файл назвали», друга — «що в ньому лежить».Стань у теку з файлами й запусти file одразу на всіх. Зірочка
означає «кожен файл у цій теці». Команда відкриє їх по черзі, зазирне в перші
байти й напише, що там насправді лежить.
Три перші рядки — це і є «спіймані»: тип не збігається з розширенням.
Ключ --mime-type дає коротку відповідь у форматі
тип/підтип. Саме її треба записувати у звіт.
Без ключа file відповідає людською мовою і значно докладніше:
Ширину й висоту file дістав із блока
IHDR — того самого, який ми бачили на схемі перших 16 байтів.
Читається так. Ліворуч офсет — номер першого байта в рядку. Посередині
16 байтів парами. Праворуч ті самі байти як текст. Крапка означає байт без
друкованого символу. Слово PNG видно неозброєним оком.
| head
Без нього xxd висипле в термінал увесь файл: для 3-мегабайтної
фотографії це близько 190 тисяч рядків. Термінал не зависне назавжди, але
прокручуватиме сміття довго. Правило: завжди | head -1
або | head -2.Ключ -C вмикає «канонічний» вигляд: байти окремо, текст у
вертикальних рисках. Файл називається пісня.pdf, а всередині
ID3 — тег MP3. Розширення бреше.
У «чистому» PowerShell немає ані file, ані xxd.
Вони приходять із Git Bash або WSL. Але подивитися байти PowerShell уміє сам:
У PowerShell команди head немає. Її роль тут грає
Select-Object -First 3 — він лишає тільки три перші рядки.
Без нього PowerShell так само висипле у вікно весь файл.
Отже, три команди відповідають на одне питання по-різному. file
каже назву формату словами. xxd і hexdump показують
самі байти, а висновок ти робиш очима. Ось те саме коротко, для двох систем.
| Задача | Git Bash / macOS / Linux | PowerShell 5.1 |
|---|---|---|
| Справжній тип файлу | file --mime-type f | немає — став Git Bash |
| Перші 16 байтів | xxd f | head -1 | Format-Hex -Path f | Select-Object -First 3 |
| Перші 32 байти | hexdump -C f | head -2 | Format-Hex -Path f | Select-Object -First 4 |
| Зберегти вивід у файл | file --mime-type * > detect.txt | … | Out-File -Encoding utf8 detect.txt |
> записує файл у кодуванні
UTF-16. Чекер читає detect.txt як UTF-8 і бачить сміття замість
твоїх рядків. Тому в PowerShell зберігай тільки через
| Out-File -Encoding utf8 detect.txt. У Git Bash, macOS і Linux
звичайне > працює правильно.Ти набрав xxd відео.mp4 без нічого — і термінал уже хвилину
сипле рядками. Що треба було написати?
У detect.txt ти написав рядок
нотатки.txt | txt | png | збіг: ні, а чекер дає червоне.
Що не так із рядком?
Уся робота — у своєму терміналі, на своєму комп'ютері. На сервер поїде тільки текст. Галочки зберігаються.
media/lesson-06/, а на сервері
~/www/lesson-06/. Не шукай lesson-11, її немає.Третє поле — завжди MIME-тип у форматі
тип/підтип, а не розширення. image/png — правильно,
png — червоний пункт у чекері.
mix лишається в локальній теці
media/lesson-06/. Там є .mp3, .jpg,
.png і сам mix.zip — FTP-приймальня відхиляє їх
автоматично. На сервер їдуть рівно три текстові файли:
index.html, detect.txt, signatures.md.Чекер знає правильні відповіді для набору наперед — самих файлів на сервері немає. Спроби не обмежені.
Демонстраційний режим: результат згенеровано для показу. На сервері
ця кнопка викликає POST /api/check, який запускає
check 06 від імені учня.
media/lesson-06/ з розпакованим набором;xxd <підозрілий файл> | head -1
і показує пальцем, де саме сигнатура;unzip -l
справді видає список файлів усередині;signatures.md узялася кожна з чотирьох сигнатур.Це те, що бачить учитель, коли виставляє оцінку.
| Складник | Вага | Результат |
|---|
Знайди на власному пристрої три файли різних типів. Для кожного запиши три
речі: ім'я, розширення і яку сигнатуру ти очікуєш побачити в hex. Потім перевір
себе командою xxd файл | head -1. У PowerShell це
Format-Hex. Познач, де твоє припущення справдилося, а де ні. Три
рядки в зошиті. На наступному уроці розберемо ті, що не справдилися.
Кожен байт у таблицях цієї сторінки взято зі специфікації формату або з офіційної документації інструмента. Перевіряти дозволено й корисно.
0D 0A 1A 0A.
w3.org/TR/png
· RFC 2083FF D8)
і ITU-T T.871 (формат обміну JFIF, маркер APP0).
itu.int/rec/T-REC-T.81
· itu.int/rec/T-REC-T.871GIF89a, ширина
й висота молодшим байтом уперед.
w3.org/Graphics/GIF/spec-gif89a.txt%PDF- на початку файлу
і рекомендація другим рядком ставити коментар із байтами понад 127.
PDF32000_2008.pdf50 4B 03 04 і поля, що йдуть за ним.
APPNOTE.TXT[Content_Types].xml усередині.
ecma-international.org · ECMA-376mimetype.
docs.oasis-open.org · ODF 1.3ID3 на початку MP3 і структура кадрів
на кшталт TIT2.
id3.org/id3v2.3.0FF FB і сусідні варіанти.
iso.org/standard/22412RIFF та ідентифікатор
WAVE на офсеті 8.
learn.microsoft.com · Resource file formatsRIFF,
але з WEBP на офсеті 8.
developers.google.com/speed/webpftyp, через який сигнатура MP4 стоїть на офсеті 4;
реєстр брендів — mp4ra.org.
iso.org/standard/831027F 45 4C 46
і байти класу та порядку байтів.
refspecs.linuxfoundation.org/elf/elf.pdffile(1) і magic(5) — як влаштована
база сигнатур і що робить ключ --mime-type.
man7.org · file(1)
· magic(5)xxd(1) і hexdump(1).
man7.org · xxd(1)
· hexdump(1)Format-Hex у PowerShell — вбудований hex-переглядач Windows.
learn.microsoft.com · Format-Hexaudio/mpeg для MP3.
iana.org · media-typesContent-Type
у HTTP; RFC 6266 — Content-Disposition.
RFC 9110
· RFC 6266> у версії 5.1
дає UTF-16 і ламає чекер.
learn.microsoft.com · about_RedirectionПовний список із поясненнями, що саме звідки взято, — у файлі
urok-11-джерела.md поруч із цією сторінкою.