# PDF 文档比较

WebSDK 从 8.5.0 版本开始,我们在完整包中新增了 PDF 文档比较接口,它提供了比较两个 PDF 文件中的文本、注释、页面对象(图片、路径)和水印差异的能力。通常来说,PDF 文档比较接口的用法是输入两个不同的文档,返回一个具有详细的差异信息的结果文档,最后打开结果文档,就可以直观地看出来两个文档的差异信息。接下来的内容将详细说明其用法和细节。

# API 预览

/docs/API_Reference/html/class_p_d_f_viewer.html#a1cd24e257a3ca64e3bd9e372457793b0 (opens new window)

# 一个简单的示例

接下来, 我们将展示如何使用文档比较接口来比较两个文档,以及控制结果文档中的内容显示。下面的示例我们将直接基于一个创建好的 PDFViewer 实例进行。

# 加载文档

在开始前,我们要先加载两个文档,这一步我们将使用 PDFViewer.loadPDFDocByFile (opens new window) 接口, 当然,你也可以使用 PDFViewer.loadPDFDocByHttpRangeRequest (opens new window) 接口。 这两个接口的作用都是加载PDF文档,然后返回 PDFDoc 对象,而不会在视图上渲染文档。

const baseDoc = await pdfViewer.loadPDFDocByHttpRangeRequest({
    range: {
        url: '/assets/compare-base.pdf'
    }
});
const otherDoc = await pdfViewer.loadPDFDocByHttpRangeRequest({
    range: {
        url: '/assets/compare-other.pdf'
    }
});

# 开始对比

我们的步骤很简单,上一步加载到文档后,只需要通过 PDFDoc.getId (opens new window) 接口获得其 id 值,然后就可以开始对比了:

const baseDocId = baseDoc.getId();
const otherDocId = otherDoc.getId();

const comparedDoc = await pdfViewer.compareDocuments(
    baseDocId,
    otherDocId,
    {
        // baseDoc 的文件名, 这将显示在结果文档中
        baseFileName: 'baseFile.pdf',
        // otherDoc 的文件名, 这将显示在结果文档中
        otherFileName: 'otherFile.pdf',
        // 结果文档的文件名,
        resultFileName: pdfViewer.i18n.t('comparison:resultFileName') || 'The result of comparison.pdf'
    }
);

效果预览:

# compareDocuments 接口参数

# 页面范围

通过以下两个参数,可以指定待比较的两个文档的页面范围:

pdfViewer.compareDocuments(
    baseDocId,
    otherDocId,
    {
        // ...
        basePageRange: {
            from: 0,
            end: 2
        },
        otherPageRange: {
            from: 1,
            end: 3
        }options: {
            // ...
        }
    }
)

basePageRange 和 otherPageRange 对象都将包括 from 和 end 属性,这两个属性表示待比较的页面起始页和结束页索引, 最终参与对比的页面将是: baseDoc: [0, 1, 2], otherDoc: [1, 2, 3], 需要注意的是, basePageRange 和 otherPageRange 指定的页数必须相同。

# options 参数

options 用于指定参与对比的对象和对比方法,其中各个参数解释如下:

// 是否对比表格, 默认为 false, 表示不对比
compareTable: false,
// 是否检测页面删除和插入, 默认为 false, 表示不检测
detectPage: false,
// 显示标记的外框宽度,单位为 point 
lineThickness: {
    delete: 2,
    insert: 2,
    replace: 2
},
// 这个参数用于设置不同差异类型的标记色,标记色格式 0xRRGGBB, 不包含透明通道,透明度需要在 opacity 中指定
markingColor: {
    delete: 0xfa0505,
    insert: 0x149bff,
    replace: 0xffcc00
},
// 这个参数用于设置不同差异类型的透明度
opacity: {
    delete: 100,
    insert: 100,
    replace: 100
},
// 是否只比较文本差异,如果值为 true, 则只比较文本差异, 如果值为 false, 则会比较注释、页面对象(包括文本)等等。
textOnly: false

使用这些参数的例子:

# 比较文档的进度

当两个文档比较大时,生成结果需要花费较多时间,compareDocuments 方法的第四个参数可以接受一个回调函数,用于获取处理进度信息:

pdfViewer.compareDocuments(
    baseDocId,
    otherDocId,
    {
        ...
    },
    (currentRate) => {
        console.log(currentRate);
    }
)

currentRate 值的范围为 0 ~ 100 。可以使用这个值在UI界面上更新进度条。

一个进度条的例子:

# 判断文档是否为比较结果文档

PDFViewer.compareDocuments 接口生成的PDF文件的字典信息可以用于判断文档是否为比较结果文档,在 SDK 中,则通过 PDFDoc.isCompareDoc() 接口判断:

pdfViewer.eventEmitter.on(PDFViewCtrl.ViewerEvent.openFileSuccess, doc => {
    doc.isCompareDoc();
})

下面是一个典型的比较结果文档的字典信息, 对象(1 0) 末尾处的 /PieceInfo 指向了 (244 0) 对象, 也就是指向了 /ComparePDF 字典项, 我们可以据此判断一个文档是否为比较结果文档。

1 0 obj
<</AcroForm 110 0 R/Pages 2 0 R/ViewerPreferences <<>>/OCProperties <</OCGs [62 0 R 63 0 R 64 0 R 65 0 R 66 0 R 67 0 R 68 0 R]/D <</Order [62 0 R 63 0 R 64 0 R 65 0 R 66 0 R 67 0 R 68 0 R]/ON [62 0 R 63 0 R 64 0 R]/OFF [65 0 R 66 0 R 67 0 R 68 0 R]>>>>/Names 367 0 R/PageLayout(TwoColumnLeft)/Type/Catalog/PieceInfo 244 0 R>>
endobj
...

244 0 obj
<</ComparePDF 235 0 R>>
endobj
...
235 0 obj
<</Private 236 0 R>>
endobj
236 0 obj
<</Differences 237 0 R>>
endobj
237 0 obj
<</Nums [1 238 0 R 2 239 0 R 3 240 0 R 4 241 0 R 5 242 0 R 6 243 0 R]>>
endobj
...