常用文件扩展名对照表
文件扩展名(Extension)是文件名末尾的标识,提示文件类型与默认打开方式。本表覆盖开发中常见的文本、代码、图片、文档、音视频与字体扩展名及含义。
原理解析
文件扩展名(如 .txt、.png、.json)是文件名末尾的片段,historically 用来提示文件类型、让操作系统选择打开程序。但它只是「约定」,不保证内容真的匹配。
真正的类型判定靠内容签名(magic number)与 MIME 类型,而非扩展名。扩展名大小写不敏感(.PNG 等同 .png),但不同系统/语言对大小写敏感的文件系统会区分;同名扩展在不同语境下也可能指向完全不同的格式。
什么时候该查这张表
这张表在你要判断某个扩展名对应什么文件类型、能不能安全地在线预览时有用。它按文档、图片、音频视频、压缩包、代码与数据分类,给出扩展名、类型与说明。选上传白名单、判断预览策略时查它。
不该查的情况:你在做 MIME 类型的严格映射或服务端内容嗅探。扩展名与真实类型不是一回事(改个后缀就能骗过),安全判断必须读文件头字节而不是看扩展名。
判断标准:先问「要不要允许在线预览」。文本类(txt/md/csv/json)可直接渲染;图片要防 SVG(可含脚本)与 SVGZ;HTML 要防 XSS;PDF 要防内嵌 JS。能下载就不要预览是更安全的原则。
特别注意双扩展名攻击:foo.pdf.html 在某些服务端按第一个点截断,或反过来按最后一个扩展名判断类型。文件上传校验必须用完整文件名比对,不能只取最后一段。
边界与常见陷阱
改后缀就能骗过基于扩展名的所有校验
把 payload.html 改名成 payload.pdf,服务端只看扩展名就会用 PDF 处理器打开并渲染其中的脚本。真正的校验必须读文件头魔数:PNG 是 89 50 4E 47,PDF 是 25 50 44 46,JPEG 是 FF D8 FF,ZIP(也是 docx/xlsx 的容器)是 50 4B 03 04。安全实现要交叉验证:声明的类型、扩展名、魔数三者必须一致,任一不符就拒绝或转存为纯文本。
SVG 是最容易被忽略的可执行文件格式
SVG 是 XML,可以内嵌 <script>、onload 事件与外部引用。直接把它当图片在 <img> 里渲染相对安全,但用 <object>/<iframe>/内联方式引入就会执行脚本。SVGZ 更是「gzip 压缩的 SVG」,扩展名完全不提示其内容。策略:上传时用 ImageMagick 等工具转成 PNG 或剥离脚本元素;或者只允许白名单里的 SVG 特性(禁 script、foreignObject、on* 事件)。
文件名本身是攻击面,双扩展名与路径穿越都要防
三类常见手法:① 双扩展名(shell.php.jpg)—— 某些服务端按第一个点截断,Apache 配错也会执行;② 路径穿越(../../etc/passwd)—— 未规范化就用原始文件名;③ 同形字/特殊字符(全角字符、零宽字符、RTL override)—— 肉眼看起来是 .jpg 实际是 .php。防护:只取 basename 并做白名单字符过滤、扩展名用白名单而非黑名单、重命名存储为随机 ID 而非原始名。
与相邻内容的分工
要查文件类型对应的 HTTP Content-Type 与 MIME 映射,用站内「MIME 类型」页;本页关注文件本身而非传输声明。
要处理具体图片文件(压缩、转换、批量处理),用站内图片工具;本页是类型判别而非处理。
要设计上传接口的存储策略(对象存储、CDN、病毒扫描),属后端架构范畴,本表不覆盖。
若目的是排查某个文件为什么打不开,先读魔数确认真实类型——扩展名与内容不符是最常见原因。
实战片段
要点:① 扩展名可以随意改写,校验必须读文件头魔数(PNG 89 50 4E 47 / PDF 25 50 44 46 / ZIP 50 4B 03 04),且扩展名、魔数、声明类型三者需一致;② SVG 是最容易被忽略的可执行格式,能内嵌 script 与 on* 事件,SVGZ 更是压缩版毫无提示,务必转码或剥离;③ 文件名本身是攻击面 —— 双扩展名、路径穿越、零宽字符三类要同时防,扩展名用白名单而非黑名单;④ 存储一律用随机 ID,原始文件名只用于展示,从根上消除目录遍历。
// ① 魔数识别(比扩展名可靠)
const MAGIC = [
{ ext: 'png', bytes: [0x89, 0x50, 0x4e, 0x47] },
{ ext: 'jpg', bytes: [0xff, 0xd8, 0xff] },
{ ext: 'pdf', bytes: [0x25, 0x50, 0x44, 0x46] },
{ ext: 'zip', bytes: [0x50, 0x4b, 0x03, 0x04] }, // 也是 docx/xlsx 容器
{ ext: 'gif', bytes: [0x47, 0x49, 0x46, 0x38] },
{ ext: 'elf', bytes: [0x7f, 0x45, 0x4c, 0x46] },
]
function sniffMime(file) {
const b = new Uint8Array(file.slice(0, 16))
for (const m of MAGIC) {
if (m.bytes.every((v, i) => b[i] === v)) return m.ext
}
return 'unknown'
}
// ② 交叉验证:扩展名 + 魔数 + 声明类型必须一致
const ALLOW = new Set(['png', 'jpg', 'pdf'])
async function safeCheck(file) {
const ext = file.name.split('.').pop().toLowerCase()
const magic = sniffMime(file)
if (!ALLOW.has(magic)) throw new Error('魔数不在白名单: ' + magic)
if (ext !== magic) throw new Error('扩展名与内容不符: ' + ext + ' vs ' + magic)
return true // ✅ 三者一致才放行
}
// ③ 🔴 文件名净化:防双扩展名 / 路径穿越 / 零宽字符
function safeName(raw) {
let n = raw.split(/[\/]/).pop() // 取 basename,丢弃路径
n = n.replace(/[-]/g, '') // 零宽字符
n = n.replace(/../g, '') // 路径穿越残留
const parts = n.split('.')
const ext = parts.pop().toLowerCase()
const base = parts.join('.') // ← 保留全部中间段,双扩展名才拦得住
if (!/^[a-zA-Z0-9_-]+$/.test(base)) throw new Error('非法文件名')
if (!ALLOW.has(ext)) throw new Error('扩展名不允许')
return base + '.' + ext
}
console.log(safeName('shell.php.jpg')) // 抛错(双扩展名)
console.log(safeName('../../etc/passwd')) // passwd(无扩展名→抛错)
// ④ 存储用随机 ID,不用原始文件名(防目录遍历与信息泄露)
import { randomUUID } from 'crypto'
const stored = randomUUID() + '.' + ext
console.log('原名仅作展示,存储名:', stored)
// ⑤ SVG 要特别处理
const DANGEROUS_SVG = /<(script|foreignObject)|sonw+=/i
if (file.name.endsWith('.svg') && DANGEROUS_SVG.test(await file.text())) {
throw new Error('SVG 含脚本或事件处理器,拒绝')
}实践注解
- 扩展名只是建议,不能当作校验依据把 a.exe 改名成 a.jpg 后扩展名就骗过了白名单。文件类型必须靠内容魔数(magic bytes)判定,扩展名最多作为展示与默认打开方式的提示。
- .tar.gz 与 .tgz 是同一格式,双扩展名要成对处理只看最后一段扩展名会得到 gz,误判为单个 gzip 流。解压逻辑应先识别 .tar.gz/.tar.bz2/.tar.xz 这类组合,再决定是否需要二次解包。
- 大小写在 Windows 与 Linux 上不一致Windows 文件系统不区分大小写,(IMAGE.PNG 与 image.png 同名);Linux 区分。做跨平台文件匹配时应统一转小写比较,否则同一份资产在两个平台上会匹配到不同文件。
数据来源
- IANA Media Types
- Platform and tooling conventions (no unified registry)
上述编号、名称与定义均来自公开规范,本站不主张对规范数据本身的独创性;本页的编排方式、中文释义与实践注解由本站撰写。
| 扩展名 | 类型 | 说明 |
|---|---|---|
| .txt | 文本 | 纯文本文件 |
| .md | 文本 | Markdown 标记文本 |
| .html | Web | 超文本标记语言页面 |
| .htm | Web | HTML 页面(短扩展名) |
| .css | Web | 层叠样式表 |
| .js | 代码 | JavaScript 脚本 |
| .ts | 代码 | TypeScript 源码 |
| .json | 数据 | JSON 数据 |
| .xml | 数据 | 可扩展标记语言 |
| .csv | 数据 | 逗号分隔值表格 |
| .yaml | 数据 | YAML 配置/数据 |
| .yml | 数据 | YAML 配置/数据(短名) |
| .toml | 数据 | TOML 配置 |
| .png | 图片 | 无损位图(支持透明) |
| .jpg | 图片 | JPEG 有损压缩图 |
| .jpeg | 图片 | JPEG 有损压缩图 |
| .gif | 图片 | 动图/无损位图 |
| .webp | 图片 | 现代高效图片格式 |
| .svg | 图片 | 矢量图形 |
| .ico | 图片 | 图标(favicon) |
| 文档 | 便携式文档 | |
| .doc | 文档 | Word 旧版文档 |
| .docx | 文档 | Word 文档(OOXML) |
| .xls | 文档 | Excel 旧版表格 |
| .xlsx | 文档 | Excel 表格(OOXML) |
| .ppt | 文档 | PowerPoint 旧版演示 |
| .pptx | 文档 | PowerPoint 演示(OOXML) |
| .zip | 压缩 | ZIP 压缩包 |
| .rar | 压缩 | RAR 压缩包 |
| .7z | 压缩 | 7-Zip 压缩包 |
| .tar | 压缩 | TAR 归档(常配合 .gz) |
| .gz | 压缩 | Gzip 压缩 |
| .mp3 | 音频 | MPEG 音频 |
| .wav | 音频 | 无损波形音频 |
| .mp4 | 视频 | MPEG-4 视频 |
| .avi | 视频 | AVI 视频容器 |
| .mov | 视频 | QuickTime 视频 |
| .woff | 字体 | Web 开放字体格式 |
| .woff2 | 字体 | Web 开放字体格式 2(更高压缩) |
| .ttf | 字体 | TrueType 字体 |
| .otf | 字体 | OpenType 字体 |
| .exe | 程序 | Windows 可执行文件 |
| .dll | 程序 | 动态链接库 |
| .apk | 程序 | Android 安装包 |
| .iso | 镜像 | 光盘镜像 |
| .log | 文本 | 日志文件 |
| .env | 配置 | 环境变量配置 |
| .sql | 数据 | SQL 脚本 |
| .db | 数据 | SQLite 数据库 |
| .sqlite | 数据 | SQLite 数据库 |
常见问题
扩展名和 MIME 类型有什么关系?
扩展名是文件名末尾的标识(如 .png),MIME 类型(如 image/png)是传输时声明内容格式的标准。服务器响应常根据扩展名设置 Content-Type,浏览器据此决定如何解析。二者并非一一对应,但多数常见扩展名有约定俗成的 MIME。
哪些图片格式适合网页?
照片用 .jpg/.webp,需透明用 .png,图标/插画用 .svg,动图用 .gif。现代站点优先 .webp 以减小体积、提升加载速度。
.docx 和 .doc 有什么不同?
.doc 是 Word 旧的二进制格式;.docx 是基于 XML 的 OOXML 压缩包格式,体积更小、更不易损坏,现代 Word 默认使用 .docx。
为什么有些文件下载后是 .zip 但其实是代码?
扩展名只影响默认打开方式,不决定真实内容。压缩包、数据集甚至恶意载荷都可能用任意扩展名。判断真实类型应看文件头(magic number)或 MIME,而非扩展名。