Skip to content

页面组织

页面组织用于调整 PDF 文档的页面结构,包括插入、删除、移动、复制、旋转、提取、合并、替换页面,以及调整页面尺寸和页面框。福昕 PDF SDK(Web)主要通过 PDFDoc 提供这些能力。

如果使用 UIExtension,部分页面组织能力也会通过缩略图面板或相关 UI 组件提供。本文重点介绍通过 API 实现页面组织。

接口概览

任务接口
获取页面信息getPageCount()getPageByIndex()PDFDoc.getAllBoxesByPageIndex();单页尺寸用 PDFPage.getWidth() / getHeight()
获取单页信息PDFPage.getIndex()getWidth()getHeight()getPageBox()getAllBoxes()isCropped()isVirtual()
插入空白页insertPage()insertBlankPages()
从 PDF 文件导入页面insertPages()
从已打开文档合并页面mergePDFDoc();多来源可对目标文档多次调用,或配合 extractPages() + insertPages()
删除页面removePage()removePages()
移动页面movePageTo()movePagesTo()
复制页面extractPages() 得到 PDF 数据后,用 insertPages() 插入到目标位置(同文档或他文档)
替换页面removePage() / removePages() 后,用 insertPages()mergePDFDoc() 写入来源页
提取页面extractPages()
导出页面到其它文档extractPages() 得到 PDF 后,对目标 PDFDoc 调用 insertPages()(或先另存为文件再打开合并)
旋转页面PDFDoc.rotatePages()PDFPage.setRotation()PDFPage.getRotation()PDFPage.getRotationAngle()
页面尺寸和页面框PDFDoc.setPagesBox()PDFDoc.getAllBoxesByPageIndex()PDFPage.setPageSize()PDFPage.getPageBox()PDFPage.getAllBoxes()

获取当前文档

javascript
const pdfViewer = await pdfui.getPDFViewer();
const pdfDoc = pdfViewer.getCurrentPDFDoc();

if (!pdfDoc) {
    throw new Error('当前没有打开文档');
}

页面范围通常使用二维数组表示。[[0]] 表示第 1 页,[[2, 4]] 表示第 3 页到第 5 页,[[0], [2, 4]] 表示第 1 页以及第 3 页到第 5 页。页面索引从 0 开始。

获取页面信息

javascript
const pageCount = pdfDoc.getPageCount();
const page = await pdfDoc.getPageByIndex(0);

// 单页逻辑尺寸(与 getWidth / getHeight 一致场景下常用)
const width = page.getWidth();
const height = page.getHeight();

// 指定页的各页面框(媒体框、裁剪框等)
const boxes = await pdfDoc.getAllBoxesByPageIndex(0);
console.log(boxes.mediaBox, boxes.cropBox);

获取到 PDFPage 后,也可以直接读取单页信息与页面框:

javascript
const pageIndex = page.getIndex();
const w = page.getWidth();
const h = page.getHeight();
// 读取某一类页面框:getPageBox(boxType),boxType 为 Box_Type 枚举,见 API Reference
const allBoxes = await page.getAllBoxes();
const isCropped = page.isCropped();
const isVirtual = page.isVirtual();

虚拟页通常不适合执行页面组织、创建表单控件、密文脱敏等会修改页面内容的操作。

插入空白页

PDFDoc.insertPage(pageIndex, width, height) 用于在指定位置插入空白页。页面尺寸单位为 point,1 英寸等于 72 point。

javascript
// 在第 1 页前插入一张 A4 尺寸空白页。
await pdfDoc.insertPage(0, 595, 842);

如果需要批量插入空白页,可以使用 insertBlankPages(pageRange, width, height)

javascript
// 插入多张空白页。
await pdfDoc.insertBlankPages([[1, 3]], 595, 842);

从其他 PDF 导入页面

PDFDoc.insertPages(options) 用于从另一个 PDF 文件中导入页面。

javascript
await pdfDoc.insertPages({
    destIndex: 1,
    file,
    password: '',
    startIndex: 0,
    endIndex: 2
});

常用参数如下:

参数说明
destIndex当前文档中的插入位置。
file来源 PDF 文件,可以是 FileBlobArrayBuffer 等。
password来源 PDF 的打开密码,可为空。
startIndex来源 PDF 起始页索引。
endIndex来源 PDF 结束页索引。
flags导入选项,0 表示普通导入,1 表示带图层导入。
layerName带图层导入时使用的图层名称。

从已打开文档合并页面

如果来源文档已经加载为 PDFDoc,可以使用 mergePDFDoc(options) 将来源文档的页面合并到当前文档。

javascript
const sourceDoc = await pdfViewer.loadPDFDocByFile(sourceFile, {
    password: ''
});

await pdfDoc.mergePDFDoc({
    doc: sourceDoc,
    insertIndex: pdfDoc.getPageCount(),
    pages: [0, 1],
    layerName: ''
});

pages 为空或未设置时,会导入来源文档的全部页面。insertIndex 小于等于 0 时插入到开头;未设置或大于等于当前页数时插入到末尾。

若需从多个已打开文档依次合并页面,可对当前文档多次调用 mergePDFDoc()(每次指定不同的 docpages),或先将来源文档 getFile() / extractPages() 得到 PDF 二进制,再对目标文档使用 insertPages()

删除页面

javascript
// 删除第 1 页。
await pdfDoc.removePage(0);

// 删除多个页面范围。
await pdfDoc.removePages([[1, 3]]);

移动页面

javascript
// 将第 1 页移动到第 4 页位置。
await pdfDoc.movePageTo(0, 3);

// 将多个页面范围移动到目标位置。
await pdfDoc.movePagesTo([[0, 2]], 5);

复制和粘贴页面

SDK 还未提供单独的“剪贴板式”复制粘贴接口。实现同文档内复制若干页到另一位置时,可先 extractPages() 得到仅含选中页的 PDF 数据,再在当前文档上 insertPages() 插入该数据。

javascript
// 将第 1 页复制到第 3 页前(destIndex = 2)。extractPages 返回的临时 PDF 仅含所提取的页。
const extracted = await pdfDoc.extractPages([[0]]);
const blob = new Blob([extracted], { type: 'application/pdf' });

await pdfDoc.insertPages({
    destIndex: 2,
    file: blob,
    password: '',
    startIndex: 0,
    endIndex: 0
});

若一次提取多页,临时 PDF 的页数为 insertPagesendIndex - startIndex + 1;可先对 extracted 使用 loadPDFDocByFile 读取 getPageCount(),或查阅 API Reference 中 extractPages / insertPages 的说明。跨文档时,对目标 PDFDoc 调用 insertPages()file 为来源文件或上一步的 Blob),或使用 mergePDFDoc()

旋转页面

PDFDoc.rotatePages(pageRange, rotation) 会修改 PDF 文档中的页面旋转信息,和 PDFViewer.rotateTo() 只改变视图显示不同。

javascript
// 将第 1 页到第 3 页旋转 90 度。
await pdfDoc.rotatePages([[0, 2]], 1);

rotation 使用 SDK 的页面旋转枚举值。常用值包括 0123,分别对应 0、90、180、270 度。

如果已经拿到 PDFPage,也可以直接设置或读取单页旋转。

javascript
const page = await pdfDoc.getPageByIndex(0);

await page.setRotation(1);

const rotation = page.getRotation();
const rotationAngle = page.getRotationAngle();

提取页面

extractPages(pageRange) 可将指定页面提取为一份新的 PDF 文档流(类型以 API Reference 为准,一般为 ArrayBuffer)。不会修改当前文档。

javascript
const extracted = await pdfDoc.extractPages([[0, 2]]);
const extractedFile = new Blob([extracted], {
    type: 'application/pdf'
});

导出页面到其它文档

将当前文档中的部分页“导出”到其它已打开的 PDFDoc 时,可先 extractPages(),再对目标文档调用 insertPages()(在目标位置插入临时 PDF 中的页范围)。

javascript
// 当前文档中提取第 1~2 页(索引 0、1),插入到 destDoc 末尾
const extracted = await pdfDoc.extractPages([[0, 1]]);
const blob = new Blob([extracted], { type: 'application/pdf' });

await destDoc.insertPages({
    destIndex: destDoc.getPageCount(),
    file: blob,
    password: '',
    startIndex: 0,
    endIndex: 1
});

若需写入多个目标文档,对每个 destDoc 重复上述插入逻辑即可。

替换页面

SDK 还未提供单独的“就地替换”接口。可用先删除再插入先插入再删除 等方式组合实现:例如用来源 PDF 的若干页替换当前文档从某索引起的连续页。

javascript
// 用来源文件中的第 1 页替换当前文档的第 1 页:先删后插
await pdfDoc.removePage(0);
await pdfDoc.insertPages({
    destIndex: 0,
    file: sourceFile,
    password: '',
    startIndex: 0,
    endIndex: 0
});

来源若为已打开的 PDFDoc,可先 getFile() 得到 Blob/FileinsertPages,或使用上文 extractPages + insertPages 的流程。

设置页面尺寸和页面框

setPagesBox(options) 可调整页面尺寸、内容偏移和页面框。常用于裁剪页面、修改页面尺寸、移除白边等场景。

javascript
await pdfDoc.setPagesBox({
    indexes: [0, 1],
    width: 600,
    height: 792,
    offsetX: 40,
    offsetY: 40,
    boxes: {
        cropBox: {
            left: 0,
            bottom: 0,
            right: 600,
            top: 792
        }
    }
});

读取指定页的页面框信息:

javascript
const boxes = await pdfDoc.getAllBoxesByPageIndex(0);

console.log(boxes.mediaBox, boxes.cropBox);

如果只需要去除白边,可以使用 removeWhiteMargin

javascript
await pdfDoc.setPagesBox({
    indexes: [0],
    removeWhiteMargin: true
});

读取单页页面框可使用 PDFPage.getPageBox(boxType)getAllBoxes()修改裁剪框等页面框请使用 PDFDoc.setPagesBox()(单页时传入 indexes: [pageIndex])。仅调整逻辑页面宽高时,可使用 PDFPage.setPageSize(width, height)

javascript
const page = await pdfDoc.getPageByIndex(0);
const pageIndex = page.getIndex();

const allBoxes = await page.getAllBoxes();
console.log(allBoxes);

await pdfDoc.setPagesBox({
    indexes: [pageIndex],
    width: 600,
    height: 792,
    offsetX: 0,
    offsetY: 0,
    boxes: {
        cropBox: {
            left: 0,
            bottom: 0,
            right: 600,
            top: 792
        }
    }
});

await page.setPageSize(600, 792);

getPageBox()boxType 取值以 API Reference 中的 Box_Type 为准(如 Media、Crop、Trim、Art、Bleed 等)。

保存修改

页面组织操作会修改当前 PDFDoc。如需下载或上传修改后的文档,请在操作完成后调用 getFile()

javascript
const file = await pdfDoc.getFile({
    fileName: 'organized.pdf'
});

注意事项

  • 页面索引从 0 开始。
  • 删除、移动、旋转等操作会改变文档结构,执行前建议确认用户意图。
  • PDFViewer.rotateTo() 只改变查看器显示;如需保存页面旋转结果,应使用 PDFDoc.rotatePages()
  • PDFPage.setRotation() 适合单页旋转;PDFDoc.rotatePages() 适合批量页面范围。
  • 调整页面框优先使用 PDFDoc.setPagesBox()(单页传入 indexes: [i] 即可);仅改宽高可用 PDFPage.setPageSize()
  • extractPages() 返回 PDF 二进制数据,不会直接修改当前文档。
  • 使用 mergePDFDoc() 时,来源 PDFDoc 在合并完成前应保持有效;若来源来自用户文件,也可用 insertPages() 避免长期持有多个文档实例。
  • 处理大文档时,建议在 UI 中展示进度或禁用重复操作,避免用户连续触发页面组织任务。