os.Stat()仅获取操作系统级元数据(大小、时间、权限等),读取EXIF、XMP、视频流、PDF作者等需专用工具如go-exiftool、go-ffprobe或pdfcpu。

直接用 os.Stat() 只能拿到基础属性(大小、修改时间、权限),真要读取 EXIF、XMP、视频流信息、PDF 作者字段这些,必须调外部工具或专用库——Go 标准库不解析文件内容层元数据。
什么时候该用 os.Stat(),什么时候必须绕开它
os.Stat() 快、轻量、不打开文件,但只返回操作系统级元数据:路径是否存在、是目录还是普通文件、大小、权限、atime/mtime/ctime。它完全不知道 JPEG 里有没有 GPS 坐标,也不知道 MP4 的宽高比或音频采样率。
- 判断文件是否存在、是否可读、是否过大 → 用
os.Stat() - 需要拍摄时间(而非修改时间)、相机型号、经纬度 → 必须用
go-exiftool或go-ffprobe - 处理 PDF 的作者、标题、创建软件 →
pdfcpu info或unidoc,os.Stat()返回空是正常的 - 视频缩略图生成、关键帧位置、DTS/PTS 时间戳 →
ffprobe输出最准,自己解析 MP4 Box 极易出错
go-exiftool 提取图片/PDF/文档元数据的硬性前提
它不是纯 Go 库,而是调用系统已安装的 exiftool 二进制。没装就 panic,不是报错——因为 NewExiftool() 内部会尝试执行 exiftool -ver,失败直接返回 error。
- Debian/Ubuntu:
sudo apt-get install exiftool - macOS:
brew install exiftool - Windows:下载 exiftool.exe 并确保在
PATH中 - 容器环境:Dockerfile 里显式安装,别只 COPY 二进制(缺少 Perl 运行时依赖)
- 调用后卡住?大概率是
exiftool启动失败,检查et, err := exiftool.NewExiftool()的err,不是等ExtractMetadata报错
go-ffprobe 解析视频时长和流信息的三个易错点
ffprobe 比任何 Go 原生解析器都可靠,但它的输出结构松散,字段存在性不保证。直接取 data.Format.Duration 很可能 panic。
立即学习“go语言免费学习笔记(深入)”;
-
Duration字段常为空:直播录制中断的 MP4、某些 TS 切片没有内建 duration,得 fallback 到streams[0].duration_ts * streams[0].time_base - 音频流不一定在
streams[1]:用循环遍历streams并检查codec_type == "audio",别硬写索引 - JSON 解析要用
json.Number接收duration字段:float64 会把"123.456"变成123.45599999999999,导致后续时间计算偏差 - HTTP URL 探测失败?
ffprobe默认不支持 HTTP range 请求,服务端若不支持206 Partial Content,会下载整个文件再解析——大视频直接超时
PDF 元信息读不出来?先确认 /Info 字典是否存在
pdfcpu info file.pdf 返回空不是 bug,是文件本身没写这个可选字典。很多导出 PDF 的工具(尤其是网页转 PDF)默认不填作者、标题等字段。
- 验证结构:
pdfcpu validate -v file.pdf确保不是损坏文件 - 查看原始对象:
pdfcpu dump file.pdf | grep -A5 "/Info",没输出就说明真没有 - 补全元数据:
pdfcpu update -author="John Doe" -title="Report Q2" input.pdf output.pdf,注意这是生成新文件,原文件不变 - 中文乱码?不是编码问题,是 PDF 内嵌字体缺失 ToUnicode 映射,
pdfcpu extract -text无法修复,只能换 unidoc 或 OCR
真正麻烦的从来不是调哪个库,而是每个文件格式的元数据都藏在不同地方、有不同可选性、甚至同一字段在不同工具里语义都不同——GPS 经度在 EXIF 里是 rational,在 XMP 里可能是 string,在 HEIC 里又套了一层。别指望一个接口打天下,先明确你要哪一层信息,再选对应工具。


















