小程序文档预览 · 进阶面试题
1. 为什么小程序预览 PDF 必须「先下载再打开」?和 H5 有什么本质区别?
答:
小程序运行在微信客户端沙箱里,没有浏览器那套完整的文档渲染能力;wx.openDocument / uni.openDocument 只接受本地路径 ,不接受远程 URL。
H5 可以用 iframe、<embed>、或直接跳转 PDF 链接,由浏览器/系统处理。小程序必须:downloadFile(或自有存储)→ 本地路径 → openDocument。
2. downloadFile 拿到的 tempFilePath 和 saveFile 后的路径有何区别?什么时候要 save?
答:
- 临时文件:本次生命周期可用,小程序退出或缓存清理后可能失效,适合「打开即看」。
- saveFile / 用户文件目录 :持久化到本地,适合「下载到手机、反复打开、离线」。
纯预览一般用临时路径即可;要做「下载保存」再saveFile,并注意存储配额与用户感知。
3. openDocument 支持哪些类型?传错 fileType 会怎样?
答: 官方常见合法值:doc/docx/xls/xlsx/ppt/pptx/pdf。
fileType 可选;传了就必须是短后缀。传 MIME(如 application/pdf)可能导致打开失败。不确定时宁可不传,让客户端按文件内容/后缀识别。
4. 合法域名校验的完整规则,面试里怎么答才算扎实?
答: 至少覆盖这几条:
request/uploadFile/downloadFile/socket分开配置,互不影响。- 仅支持 HTTPS(socket 为 WSS),不能用裸 IP(特殊局域网场景除外)、不能用 localhost。
- 端口绑定 :配置不含端口则 URL 也不能带端口;配置了
:9220就只能访问该端口。 - 域名需备案、证书有效。
- 开发者工具「不校验合法域名」不等于预览码/体验版/正式版不校验。
能对比「真机调试能过、预览失败」是加分项。
5. downloadFile 的 success 里 statusCode !== 200 为什么仍可能进 success?
答: 文档说明:只要服务器有响应并把内容写入文件,就可能走 success。业务必须自己判断 statusCode,以及文件是否有效(避免把 404 HTML 当成 PDF 打开)。
6. 大文件预览有哪些坑?如何设计?
答:
- 有单次下载大小上限(官方约 200MB 量级,以当前文档为准)。
- 弱网耗时长,需 loading、超时、失败重试与取消策略。
- 并发:同时点多个文件要排队或加锁(类似
fileBusy)。 - 体验:大文件可提示大小、仅 Wi‑Fi 下载,或改为「复制链接到浏览器打开」(若产品允许)。
7. 除了 openDocument,还有哪些预览方案?各有什么取舍?
答:
| 方案 | 优点 | 缺点 |
|---|---|---|
| downloadFile + openDocument | 官方能力,体验接近系统文档 | 依赖域名;类型有限 |
| web-view 打开在线预览页 | 可做水印、权限、转码预览 | 需业务域名;实现重 |
后端转图片/多页图再 previewImage |
兼容性好、可控 | 清晰度、页数、成本 |
| 仅提供下载/复制链接 | 实现简单 | 跳出小程序,转化差 |
面试应能按「合规、体验、成本」选型。
8. 文件 URL 带鉴权(token、签名、过期时间)时怎么预览?
答:
downloadFile支持header(不能改 Referer)。签名放 Query 或 Header 均可,但 URL 过期要在打开前刷新。- 若签名域名与业务 API 不同,两边合法域名都要配。
- 安全上:短时签名、防盗链、避免把长期 token 打进前端日志。
9. 为什么生产环境常见「图片能显示、PDF 不能预览」?
答: 图片多用 <image>,走的是图片域名/下载策略;PDF 必须走 downloadFile,校验的是 downloadFile 合法域名。两者列表独立,只配了 request/upload 或图片相关域,PDF 仍会挂。
10. iOS / Android 在文档预览上可能有什么差异?
答:
- 打开器是系统能力,UI、分享菜单、部分格式兼容性可能不同。
- 临时文件生命周期、权限提示表现不一致。
- 线上问题要分端复现;不要只在开发者工具或单一机型验收。
11. 如果 fileUrl 是 HTTP 或证书有问题,会怎样?
答: 正式环境要求 HTTPS 且证书链可信。HTTP、自签证书、SNI/中间证书缺失,预览码场景常直接 download 失败。开发期不校验域名时可能「看起来能用」,上线必曝。
12. 如何从架构上避免「前端直链 MinIO/OSS 预览」带来的域名与安全问题?
答:
- 文件走统一 HTTPS 网关(443),合法域名只配一个稳定域名。
- 或由后端鉴权代理下载:小程序只请求已在 downloadFile 白名单内的业务域名。
- 对象存储用临时签名 URL,不把永久密钥下发到小程序。
13. 手写一段伪代码,体现「可取消、防重入、错误可区分」?
答(思路即可):
text
if (busy) return
busy = true
task = downloadFile(url)
onSuccess:
if status != 200 → toast 下载失败(可展示 status)
else openDocument(tempPath)
onFail → toast 打开失败(与下载失败区分文案)
onFail:
if msg contains domain → toast 域名未配置
else toast 网络/下载失败
finally:
busy = false
能区分「域名问题 / 下载失败 / 打开失败」比只弹「预览失败」更专业。
14. 追问:预览过程中用户返回上一页,要注意什么?
答: loading 要在页面卸载时 hideLoading;busy 复位;若有下载任务可忽略回调或校验页面仍存活,避免卸载后 setData/toast 报错。openDocument 已打开则由系统页接管,一般无需前端强杀。
15. 一道综合题:让你设计「小程序内合同预览」能力,你会怎么答?
答建议结构:
- 协议 :后端返回短时签名的 HTTPS
fileUrl+ 文件名/类型/大小 - 前端:进页拉取 → 点击预览 → download + openDocument;防重入、状态提示、错误分类
- 基础设施:单一文件域名(尽量 443)、downloadFile 白名单、证书与备案
- 安全:鉴权、水印(若合规要求则转 web-view/图片方案)、日志脱敏
- 验收:必须以预览码/体验版验证,覆盖双端与弱网
面试加分点: 能讲清「本地路径限制」「域名与端口绑定」「临时文件 vs 持久化」「download 与 open 错误分离」「直链 OSS vs 网关/代理」------说明你不是只会抄两行 API,而是理解小程序网络与系统能力边界。