Files
reader/docs/pdf.md

27 lines
2.1 KiB
Markdown

# PDF 在线与离线阅读
PDF 使用 PDF.js 在 Web Worker 中解析,当前页由 Canvas 和可选择的文本层显示。
每页对应阅读器的一个固定布局 section,翻页、目录、页码和阅读位置沿用现有机制。
## 在线打开
1. 优先检查当前服务器、账户下已下载的完整文件缓存。
2. 没有完整缓存时,仅通过 `HEAD /api/v1/books/:id/content` 获取长度与 Range 能力。
3. PDF.js 通过自定义 `PDFDataRangeTransport` 按需读取字节区间,块大小为 64 KiB;禁用流式全量下载和自动预取。
4. 每个 Range 请求走现有客户端 Transport,携带 Authorization,并沿用令牌续期、401 重试、账户切换检查与取消机制。令牌不会写入 PDF URL。
5. 服务端直接从请求的文件偏移读取,不再读取并丢弃区间前面的字节。
64 KiB 是分块粒度,不是首屏流量上限;实际读取量由 PDF 的索引、字体、图片和页面内容布局决定,部分文档仍可能需要读取大量数据。
代理必须保留 `HEAD`、`Range`、`Content-Length`、`Accept-Ranges` 和 `Content-Range`;不支持 Range 时显示错误,不隐式回退到完整下载。
## 离线与资源管理
在线阅读不会自动缓存完整 PDF。需要离线时使用现有的整书下载功能;之后从账户隔离的完整文件缓存打开。
PDF.js worker、CMap、标准字体和 WASM 解码资源随构建打包,由现有 PWA 机制缓存,不依赖外部 CDN。
切换页面会取消旧的渲染,关闭阅读器会取消请求、释放画布并销毁文档 worker。尺寸变化自动重绘;支持完整页面和适合宽度两种模式。
## 验证
在 `web` 目录执行 `npm run ui:review:pdf`。脚本使用真实 Chromium 和带大段未引用数据的 8 MiB PDF,禁止不带 Range 的 GET,检查首屏流量、空闲时不预取、鉴权、文本层、页面跳转、尺寸变化及资源释放。
流量统计只计算 PDF 数据,不含阅读器脚本、worker、字体等静态资源。该构造样本用于验证按需读取机制,不代表真实扫描书的性能基准;尚需在实际书籍和 Android 真机上验收。