打印、拼版、加水印之前,先得知道每一页是横版还是竖版:横竖混排的文档直接打印会留白边,拼版也会错位。页面还可能被整体旋转过,这时候记录的页面尺寸和肉眼看到的方向就对不上了。批量处理前想把这类页面挑出来,用桌面软件只能一页页翻。
本文介绍用 Spire.PDF for JavaScript 检测 PDF 页面的旋转角度与显示方向。它基于 WebAssembly 在浏览器端直接加载与解析 PDF 文档,全过程在本地完成,通过虚拟文件系统(VFS)读写文件,无需后端配合。
本文介绍两个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.PDF for JavaScript。以下示例默认已安装 Spire.PDF 并完成 WebAssembly 模块初始化。
检测页面的旋转角度
PdfPageBase.Rotation 用来读取页面被旋转的角度,取值落在 PdfPageRotateAngle 枚举的 0°、90°、180°、270° 之内。
function App() {
const detectPageRotation = async () => {
// 获取 Spire.PDF WASM 模块
const pdfModule = window.wasmModule?.spirepdf;
// 检查模块是否就绪
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// 将待检测的 PDF 文件载入 VFS
const inputFileName = '页面方向样例.pdf';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// 创建 PdfDocument 对象并加载 PDF 文档
const doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// 枚举的数值是序号而不是角度,先建立序号到角度的映射
const DEGREES = {
[pdfModule.PdfPageRotateAngle.RotateAngle0.value]: 0,
[pdfModule.PdfPageRotateAngle.RotateAngle90.value]: 90,
[pdfModule.PdfPageRotateAngle.RotateAngle180.value]: 180,
[pdfModule.PdfPageRotateAngle.RotateAngle270.value]: 270,
};
// 逐页读取旋转角度
const lines = [];
for (let i = 0; i < doc.Pages.Count; i++) {
const page = doc.Pages.get_Item(i);
lines.push(`第 ${i + 1} 页:旋转角度 ${DEGREES[page.Rotation.value]}°`);
}
// 检测结果写入 VFS
const outputFileName = '旋转角度检测结果.txt';
window.dotnetRuntime.Module.FS.writeFile(outputFileName, lines.join('\r\n'));
doc.Close();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>检测页面旋转角度</h1>
<button onClick={detectPageRotation}>
开始检测
</button>
</div>
);
}
export default App;
逐页记录旋转角度的检测结果:

检测页面的显示方向
判断页面是横是竖不能只看尺寸:PdfPageBase.Size 给出的是可见页面框的宽高,不含旋转;页面被旋转 90° 或 270° 时,显示出来的宽高要对调,才是页面实际的方向。
function App() {
const detectPageOrientation = async () => {
// 获取 Spire.PDF WASM 模块
const pdfModule = window.wasmModule?.spirepdf;
// 检查模块是否就绪
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// 将待检测的 PDF 文件载入 VFS
const inputFileName = '页面方向样例.pdf';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// 创建 PdfDocument 对象并加载 PDF 文档
const doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
const { RotateAngle90, RotateAngle270 } = pdfModule.PdfPageRotateAngle;
// 逐页判断显示方向
const lines = [];
for (let i = 0; i < doc.Pages.Count; i++) {
const page = doc.Pages.get_Item(i);
const pageSize = page.Size;
// Size 不含旋转:旋转 90° 或 270° 时宽高对调,才是实际显示尺寸
const quarterTurn = page.Rotation === RotateAngle90 || page.Rotation === RotateAngle270;
const width = quarterTurn ? pageSize.Height : pageSize.Width;
const height = quarterTurn ? pageSize.Width : pageSize.Height;
const orientation = width >= height ? '横向' : '纵向';
lines.push(`第 ${i + 1} 页:${orientation}(${width.toFixed(0)} × ${height.toFixed(0)} 磅)`);
}
// 检测结果写入 VFS
const outputFileName = '页面方向检测结果.txt';
window.dotnetRuntime.Module.FS.writeFile(outputFileName, lines.join('\r\n'));
doc.Close();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>检测页面显示方向</h1>
<button onClick={detectPageOrientation}>
开始检测
</button>
</div>
);
}
export default App;
按显示方向逐页判断后的检测结果:

常见问题
page.Rotation.value 读到的是 0、1、2、3,而不是 0、90、180、270
原因:PdfPageRotateAngle 的四个成员 RotateAngle0、RotateAngle90、RotateAngle180、RotateAngle270 在 WebAssembly 绑定里的数值依次是 0、1、2、3,.value 取到的是这个序号,而不是角度值。写成 page.Rotation.value === 90 恒为 false。
解决:建立序号到角度的映射再使用。要修正旋转时也传序号——page.Rotation 收的是序号,传 90 会被当成序号 2,实际写进文档的是 180°:
// 序号 → 角度
const DEGREES = {
[pdfModule.PdfPageRotateAngle.RotateAngle0.value]: 0,
[pdfModule.PdfPageRotateAngle.RotateAngle90.value]: 90,
[pdfModule.PdfPageRotateAngle.RotateAngle180.value]: 180,
[pdfModule.PdfPageRotateAngle.RotateAngle270.value]: 270,
};
// 把当前页修正为 90°,.value 就是序号
page.Rotation = pdfModule.PdfPageRotateAngle.RotateAngle90.value;
页面明明是横版,page.Size 返回的却是竖版尺寸
原因:PdfPageBase.Size 与 ActualSize 返回的是页面可见框的宽高——设过 CropBox 就是 CropBox,否则是 MediaBox——这个值不随 /Rotate 变化。示例文档第 3 页的页面框是 595 × 842 磅,/Rotate 为 90°,渲染出来是 842 × 595 的横版,Size 依旧返回 595 × 842。
解决:读到 Rotation 之后自己把宽高对调:
const { RotateAngle90, RotateAngle270 } = pdfModule.PdfPageRotateAngle;
const quarterTurn = page.Rotation === RotateAngle90 || page.Rotation === RotateAngle270;
const width = quarterTurn ? page.Size.Height : page.Size.Width;
const height = quarterTurn ? page.Size.Width : page.Size.Height;
载入的 PDF 里 doc.Sections 是空的,PageSettings.Orientation 也读不到
原因:Sections 是页面设置的容器,LoadFromFile 载入已有 PDF 时不会为现成页面重建节,doc.Sections.Count 为 0,接着调 doc.Sections.get_Item(0) 会抛 Arg_IndexOutOfRangeException。PageSettings.Orientation 描述的是新建页面时的排版意图,也不是文件里记录的方向。
解决:检测已有页面只走页级属性,doc.Pages.get_Item(i) 之后读 Rotation 与 Size;PageSettings.Orientation 留给 Sections.Add() 新建页面时使用:
// 检测已有页面
const page = doc.Pages.get_Item(0);
const angle = DEGREES[page.Rotation.value];
// 新建页面时才用得到 Orientation
const section = doc.Sections.Add();
section.PageSettings.Orientation = pdfModule.PdfPageOrientation.Landscape;
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。









