判断文件能否预览的核心是依据真实 MIME 类型与白名单校验,而非扩展名;需流式读取、编码检测、截断控制;PDF/图片须生成轻量缩略图并异步处理;preview 接口应拆分为元信息与内容两个路由以提升缓存与性能。
怎么判断一个文件能不能预览
核心是看文件内容是否能被安全转成文本或标准格式,而不是只看后缀名。比如
肯定行,但
需解压+解析 XML,
得调用解析库,而
或加密的
就不该进预览流程。
实操建议:
立即学习
“
go语言免费学习笔记(深入)
”;
先用
库(如
)读取文件前 512 字节,识别真实类型,比
可靠得多
维护一个白名单:只允许
、
、
、
(缩略图)、
等明确支持的类型
对
这类泛型类型,直接拒绝,不尝试猜测
特别注意:PDF 和 Office 文档要加超时和内存限制,否则恶意构造的大文件会卡死服务
文本文件怎么安全读取和截断
不能直接
整个文件——用户上传 2GB 的日志文件会把内存打爆。得流式读、按需截、防编码乱码。
实操建议:
立即学习
“
go语言免费学习笔记(深入)
”;
用
+
控制最大读取字节数(比如 1MB),超过就截断并标记“已截断”
检测编码用
+
库,优先试
,失败再 fallback 到
(中文场景),别硬转
换行统一处理成
,避免前端渲染错乱;行数限制建议设为 1000 行,不是字节数
敏感路径(如
)或含控制字符(
、
)的内容,直接返回空或报错,不清洗后展示
PDF 和图片怎么生成轻量预览
PDF 不渲染全文,图片不原图返回——目标是快、小、可缓存。重点不在“还原”,而在“够看”。
实操建议:
立即学习
“
go语言免费学习笔记(深入)
”;
Pdf:用
或更轻的
提取第一页为 PNG,尺寸固定为
,质量压缩到 75%,超时设为 3 秒
图片:用
缩放,保持宽高比,最长边不超过 1200px;WebP 格式优先(体积小),但 IE 用户降级为 JPEG
所有缩略图加
,路径里嵌入文件 hash(如
.webp),避免 CDN 缓存错乱
别在 HTTP handler 里实时生成——先异步写入
或对象存储,再 302 跳转,不然并发一高就堵住
为什么 preview 接口要拆成两个路由
一个返回元信息(能否预览、类型、大小、页数),一个返回实际内容(文本片段或缩略图 URL)。合在一个接口里,会导致缓存失效、CDN 不友好、前端逻辑耦合。
实操建议:
立即学习
“
go语言免费学习笔记(深入)
”;
元信息接口如
,响应快(can_preview、
、
(PDF)、
内容接口如
或
,不缓存或短缓存,带鉴权校验
前端必须先调 meta,再决定要不要发 content 请求——避免对不可预览文件浪费一次网络请求
meta 接口要记录
和
,方便后续识别爬虫或异常批量请求
最麻烦的其实是 PDF 的字体嵌入和权限位检查——有些 PDF 设置了“禁止复制文字”,
默认会报错,得提前用
检查
并跳过这类文件。这事容易漏,上线后才发现部分 PDF 打不开。
.txt.docx.pdf.exe.zipmimetypegithub.com/gabriel-vasile/mimetypefilepath.Exttext/*application/jsonapplication/xmlimage/*application/pdfapplication/octet-streamos.ReadFilebufio.NewReaderio.LimitReadergolang.org/x/text/encodingcharsetUTF-8GBK\n/etc/passwd\x00-\x08\x0E-\x1Fgithub.com/unidoc/unipdf/v3/creatorgithub.com/jung-kurt/gofpdf800x1200github.com/disintegration/imagingCache-Control: public, max-age=86400/thumb/sha256/tmp/thumbs/GET /api/v1/preview/meta?file_id=abc123mime_typepage_countis_truncatedGET /api/v1/preview/content?file_id=abc123&type=textGET /api/v1/preview/thumb?file_id=abc123user_agentrefererunipdfpdfcpupdfcpu validate