文件上传、媒体处理和资源校验这类场景里,判断文件类型几乎是基础动作。但只看 .jpg、.png 这样的后缀名并不稳妥,因为扩展名可以随手改掉,真正有意义的是文件内容本身暴露出来的 MIME 类型。下面就用 Go 里最常见的两种做法拆开来看:先看标准库怎么实现,再看第三方库在识别信息上能补到什么程度。
为什么不能只看文件后缀
在日常开发中,很多人会先从文件名入手判断类型,比如上传图片时检查是不是 jpg、png。这种方式实现简单,但并不可靠。
原因很直接:文件后缀是可以修改的。一个恶意程序完全可以伪装成 .jpg 再上传,如果系统只认文件名,不认内容,就可能把不该接收的文件放进业务流程,进而带来安全隐患。
更稳妥的做法,是读取文件内容的前几个字节,通过文件头特征来判断它的真实类型。对应到程序里,通常就是获取文件的 MIME 类型。
用 Go 标准库获取 MIME 类型
Go 标准库已经提供了现成能力。在 net/http 包里,可以直接使用 http.DetectContentType 判断内容类型。
这个方法的关键点在于:不需要把整个文件都读完,一般取前 512 个字节就可以完成识别。因此它很适合放在上传校验、文件预检查这类场景里。
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
fi, err := os.Open("/path/videos/pkch.mp4")
if err != nil {
panic(err)
}
// 只需要前 512 个字节就可以了
buffer := make([]byte, 512)
_, _ = fi.Read(buffer)
contentType := http.DetectContentType(buffer)
fmt.Println(contentType) // video/mp4
}
这段代码的处理流程很直接:
读取文件头
先通过 os.Open 打开文件,然后分配一个 512 字节的缓冲区。这里读取的不是完整文件,而是用于识别类型的前导内容。
调用识别函数
http.DetectContentType(buffer) 会根据这段字节数据返回 MIME 类型。示例里输出结果是 video/mp4。

适用场景
如果你的需求只是做基础类型判断,例如限制上传文件必须是图片、音频或视频,标准库通常已经够用。它没有额外依赖,接入成本也最低。
第三方库实现:filetype
如果你希望使用专门做文件类型识别的库,也可以考虑 github.com/h2non/filetype。它同样基于文件头判断类型,写法也比较直接。
package main
import (
"fmt"
"os"
"github.com/h2non/filetype"
)
func main() {
fi, err := os.Open("/path/videos/pkch.mp4")
if err != nil {
panic(err)
}
// We only have to pass the file header = first 261 bytes
buffer := make([]byte, 261)
_, _ = fi.Read(buffer)
kind, _ := filetype.Match(buffer)
if kind == filetype.Unknown {
fmt.Println("Unknown file type")
return
}
fmt.Println(kind.MIME.Value) // video/mp4
}
和标准库相比,这个库的示例中只读取了前 261 个字节,然后调用 filetype.Match(buffer) 进行匹配。
返回结果的处理方式
这里先判断 kind == filetype.Unknown,如果没有识别出来,就输出 Unknown file type 并返回。识别成功时,再通过 kind.MIME.Value 取到 MIME 字符串,例如 video/mp4。
适合什么情况
当你不只想拿到一个基础 MIME 值,还希望借助更专门的匹配逻辑做扩展识别时,第三方库会更方便一些。代价则是需要引入额外依赖,并在项目里维护它的版本。
标准库和第三方库怎么选
如果只是一般业务校验,优先用标准库往往更合适。原因很简单:调用少、依赖少、可维护性也更好。对于大多数上传接口、资源检查流程,http.DetectContentType 已经能满足需求。
如果项目本身对文件类型识别有更细的要求,或者你已经在使用相关生态库,那么再考虑接入 github.com/h2non/filetype 也不迟。
无论选哪种方案,核心原则都一样:不要只信后缀名,应该基于文件头判断真实内容类型。对 Go 项目来说,这也是实现成本和安全性之间比较平衡的一种做法。














