面向程序员的 PDF 操作





5.00/5 (7投票s)
本教程将解释 PDF 操作、其重要性以及用例。
PDF 操作,最简单的形式是创建、读取和编辑 PDF 文件。由于这些文件广泛用于多个行业的许多目的,因此您能够在软件或应用程序中操作 PDF 文件非常重要。
本教程将解释 PDF 操作、其重要性以及用例。它还将演示开发人员在创建 PDF 操作工具时面临的一些挑战,以及如何使用 Foxit 的 SDK 库轻松解决这些挑战。
访问 Foxit PDF SDK Web 演示,通过探索配置和功能来亲眼看看.
为什么要使用 PDF 操作
将文档和文件存储为 PDF 已变得至关重要,因为 PDF 是包含文本、图形或其他数据的文件的易于共享的副本。PDF 文件使企业和政府能够存储、阅读和共享文档,同时确保文件符合其数据保留策略。
随着对 PDF 文件的依赖日益增长,对创建、编辑和读取这些文件的需求也随之而来。企业可能还需要合并文件或从中删除页面。这些以及其他类型的更改,例如添加签名、注释或添加评论的能力,都属于 PDF 操作的范畴。
随着每个用例所需的功能和特性不断扩展,PDF 操作成为程序员的一项越来越重要的技能。
PDF 操作的挑战
PDF 文件旨在易于查看和共享,因此对其进行操作可能很困难。这会使构建 PDF 操作工具变得更具挑战性。
以下是涉及的一些挑战以及如何使用 Foxit 的 SDK 解决这些挑战。
您可以在 这个 GitHub 存储库 中找到这些示例的代码。
解码和读取 PDF 文件
任何 PDF 操作工具的一个基本部分是允许用户查看他们的 PDF 文件。即使是最流行的库,实现起来也可能很困难。
不使用 Foxit
假设我们要构建一个允许用户打开和查看 PDF 文件的 PDF 查看器。使用流行的 JavaScript 库 PDF.js,代码将类似于此
<input type="file" name="pdf" id="pdf_input" />
<canvas id="pdf" style="display: block;"></canvas>
<script src=""></script>
<script>
const fileInput = document.getElementById("pdf_input");
const pdfElement = document.getElementById("pdf");
pdfjsLib.workerSrc = '';
//bind change event to file input
fileInput.addEventListener('change', decodePDF)
function decodePDF() {
const fileReader = new FileReader();
fileReader.readAsDataURL(fileInput.files[0]);
fileReader.onloadend = function (event) {
convertToBinary(event.target.result);
}
}
const BASE64_MARKER = ';base64,';
function convertToBinary(dataURI) {
const base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
const base64 = dataURI.substring(base64Index);
const raw = window.atob(base64);
const rawLength = raw.length;
const array = new Uint8Array(new ArrayBuffer(rawLength));
for (let i = 0; i < rawLength; i++) {
array[i] = raw.charCodeAt(i);
}
getPDF(array);
}
function getPageText(pageNum, PDFDocumentInstance) {
// Return a Promise that is solved once the text of the page is retrieved return new Promise(function (resolve, reject) {
PDFDocumentInstance.getPage(pageNum).then(function (pdfPage) {
// The main trick to obtain the text of the PDF page, use the getTextContent method
pdfPage.getTextContent().then(function (textContent) {
const textItems = textContent.items;
let finalString = "";
// Concatenate the string of the item to the final string for (let i = 0; i < textItems.length; i++) {
const item = textItems[i];
finalString += item.str + " ";
}
resolve(finalString);
});
});
});
}
function getPDF(pdfAsArray) {
pdfjsLib.getDocument(pdfAsArray).promise.then(function (pdf) {
for(let i = 1; i <= pdf._pdfInfo.numPages; i++) {
pdf.getPage(i).then(function (page) {
const scale = 1.5;
const viewport = page.getViewport({ scale: scale, });
const canvas = document.getElementById('pdf');
const context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
const renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
})
}
}).catch(console.error);
}
</script>
此代码允许用户通过文件输入选择 PDF 文件。该文件以 base64 字符串的形式检索,然后转换为字节数组并传递给 PDF.js 的 getDocument
方法。这允许您遍历 PDF 的页面并将文件渲染到画布元素中。
正如您所见,当用户选择文件时,它会正确显示 PDF。
使用 Foxit 的 SDK
Foxit 的 SDK 使查看过程更轻松。这是创建阅读器的代码
<input type="file" name="pdf" id="pdf_input" />
<div id="pdf"></div>
<script src="/license-key.js"></script>
<script src="/lib/PDFViewCtrl.full.js"></script> <script> const fileInput = document.getElementById("pdf_input");
const pdfViewer = new PDFViewCtrl.PDFViewer({
libPath: '/lib',
jr: {
licenseSN: licenseSN,
licenseKey: licenseKey,
tileSize: 300,
},
});
pdfViewer.init('#pdf');
function decodePDF (e) {
pdfViewer.openPDFByFile(fileInput.files[0]);
}
fileInput.addEventListener('change', decodePDF);
</script>
请务必加载您在下载 SDK 时收到的 license-key.js 和 /lib/PDFViewCtrl.full.js 脚本。然后初始化 PDF 查看器并指定应在其上渲染 PDF 的 HTML 元素。使用 openPDFByFile
方法查看用户选择的文件。
运行代码时,请注意它不仅成功渲染了 PDF,而且质量也大大提高了。Foxit 的渲染引擎之所以能够取得更好的效果,是因为它经过开发,即使是大型、复杂的文档,也能快速提供最佳质量的图像。
添加和查看注释
共享或协作处理 PDF 文件的一部分是能够对文件进行注释或添加评论。
如果您要在 PDF 操作工具功能中添加注释,您需要将注释绘制到 PDF 中,而不是将其添加为文本。要添加注释,您需要在一个特定坐标(通常由用户选择)处添加一个矩形,然后将文本插入该矩形内。
这是因为 PDF 文件旨在用于查看而不是操作,而简单地将文本添加到文档中将不起作用。此格式最重要的是输出数据的视觉效果。因此,添加注释可能具有挑战性,尤其是因为用户需要在导出文件后在任何支持的 PDF 查看器上看到这些注释。
使用 Foxit 的 SDK
Foxit 的 SDK 包含一个完整的编辑器,该编辑器提供开箱即用的支持,用于在 PDF 文件中添加、查看和正确导出注释。要使用注释和评论,请包含从下载的 SDK 中所需的所有脚本,并添加一个用于渲染编辑器的 HTML 元素
<head>
<link rel="stylesheet" href="/lib/UIExtension.css">
<script src="/lib/adaptive.js"></script>
</head>
<body>
<div id="pdf"></div>
<script src="/license-key.js"></script> <script src="/lib/UIExtension.full.js"></script> <script src="/lib/preload-jr-worker.js"></script>
然后添加一个首先初始化 PDF UI 的脚本
const readyWorker = preloadJrWorker({
workerPath: '/lib/',
enginePath: '/lib/jr-engine/gsdk',
licenseSN: licenseSN,
licenseKey: licenseKey
});
const pdfui = new UIExtension.PDFUI({
viewerOptions: {
libPath: '/lib',
jr: {
readyWorker: readyWorker
}
},
renderTo: '#pdf',
appearance: UIExtension.appearances.adaptive,
addons: UIExtension.PDFViewCtrl.DeviceInfo.isMobile ?
'/lib/uix-addons/allInOne.mobile.js':
'/lib/uix-addons/allInOne.js'
});
//open a ready file
pdfui.openPDFByHttpRangeRequest({
range: {
url: '/Sample.pdf',
}
}, { fileName: 'Sample.pdf' });
这将使用 Foxit SDK 提供的 UI 初始化 PDF 查看器,其中添加了包括评论和注释在内的功能。
您可以在 PDF 查看器中添加和查看评论。
当您下载 PDF 文件时,您将能够在其他 PDF 查看器中查看注释。
在浏览器中尝试我们的 SDK Web 演示,无需下载或登录.
数字签名
数字签名在某些企业中经常使用,但确保其安全性和有效性可能很复杂。
签名文档需要几个步骤
- 打开文档并添加 UI 以允许用户签名文档。
- 将签名转换为文件流。
- 计算带有签名的文档的消息摘要。
- 使用签名者的数字私钥(如 p12 文件)以及您的证书或密钥加密消息和文档。
- 将加密的签名数据写入文件流。
然后,您需要执行以下步骤在服务器上验证签名数据
- 获取原始 PDF 文档的内容、签名范围、签名数据和签名者信息。
- 计算带有签名范围的内容的消息摘要。
- 将计算出的摘要与签名数据进行验证。
如您所见,此过程很复杂,从头开始构建它可能会很麻烦。
使用 Foxit 的 SDK
Foxit 的 SDK 提供了现成的 API,可以执行整个过程。
要在 PDF 操作工具中添加数字签名功能,首先要初始化 Foxit 的 PDF UI。(上一节已包含此代码。)
除其他功能外,SDK 还提供了一个用于数字签名的签名字段。
然后添加一个签名处理程序。当用户签署签名表单字段时,处理程序会将与签名和签名者相关的数据与 PDF 转换为文件流,然后将 Blob 发送到服务器。服务器会计算签名的消息摘要并返回签名文档。
pdfui.registerSignHandler({
filter: 'Adobe.PPKLite',
subfilter: 'adbe.pkcs7.sha1',
flag: 0x100,
distinguishName: 'e=support@yourcompany.com',
location: 'FZ',
reason: 'Test',
signer: 'web sdk',
showTime: true,
sign: function(setting, buffer) {
const formData = new FormData();
formData.append('plain', new Blob([buffer]));
return fetch('https://webviewer-demo.foxitsoftware.com/signature/digest_and_sign', {
method: 'POST',
body: formData
}).then((response) => response.arrayBuffer());
}
});
上面的示例使用了 Foxit 的 测试服务器。使用 Foxit 提供的示例,您的服务器的 digest_and_sign
代码可能如下所示
router.post('/digest_and_sign', koabody({ multipart: true }), async (ctx) => {
fs.copyFileSync(ctx.request.files.plain.path, '.\\temp\\plain');
let { filter, subfilter, signer, md } = ctx.request.body;
if (!md) md = 'sha1';
if (!subfilter) subfilter = 'adbe.pkcs7.detached';
if (subfilter == 'adbe.pkcs7.sha1') {
process.execSync(
'.\\bin\\pkcs7.exe digest .\\temp\\plain .\\temp\\sha1'
);
process.execSync(
'.\\bin\\pkcs7.exe sign .\\bin\\foxit_all.pfx 123456 .\\temp\\sha1 .\\temp\\signedData'
);
} else if ((subfilter = 'adbe.pkcs7.detached')) {
switch (md) {
case 'sha1':
md = '0';
break;
case 'sha256':
md = '1';
break;
case 'sha384':
md = '2';
break;
}
process.execSync(
'.\\bin\\pkcs7.exe sign .\\bin\\foxit_all.pfx 123456 .\\temp\\plain .\\temp\\signedData Yes ' +
md
);
}
ctx.body = fs.createReadStream('.\\temp\\signedData');
return;
});
请注意,此代码要求您使用 PKCS7 和 PFX 密钥。
接下来是验证步骤。要验证 PDF 的签名,请将消息摘要以及与签名和签名者相关的所有数据发送到服务器
pdfui.setVerifyHandler(function (signatureField, plainBuffer, signedData){
const formData = new FormData();
formData.append('filter', signatureField.getFilter());
formData.append('subfilter', signatureField.getSubfilter());
formData.append('signer', signatureField.getSigner());
formData.append('plainContent', new Blob([plainBuffer]));
formData.append('signedData', new Blob([signedData]));
return fetch('https://webviewer-demo.foxitsoftware.com/signature/verify', {
method: 'POST',
body: formData
}).then((response) => response.text());
});
当 Foxit SDK UI 中的签名签名字段被点击时,将执行此处理程序
同样,这使用的是 Foxit 的测试服务器来验证签名。如果您想在服务器上验证签名,代码将如下所示
router.post('/verify', koabody({ multipart: true }), async (ctx) => {
let { filter, subfilter, signer } = ctx.request.body;
fs.copyFileSync(
ctx.request.files.plainContent.path,
'.\\temp\\plainBuffer'
);
fs.copyFileSync(ctx.request.files.signedData.path, '.\\temp\\signedData');
if (subfilter == 'adbe.pkcs7.sha1') {
process.execSync(
'.\\bin\\pkcs7.exe digest .\\temp\\plainBuffer .\\temp\\digest'
);
process.execSync(
'.\\bin\\pkcs7.exe verify .\\temp\\signedData .\\temp\\digest .\\temp\\output'
);
} else if ((subfilter = 'adbe.pkcs7.detached')) {
process.execSync(
'.\\bin\\pkcs7.exe verify .\\temp\\signedData .\\temp\\plainBuffer .\\temp\\output'
);
}
ctx.body = fs.createReadStream('.\\temp\\output');
});
结论
随着对使用、共享和协作处理 PDF 文件的需求增加,将 PDF 操作工具集成到您的系统或应用程序中是必不可少的。然而,PDF 的设计初衷是为了让多个用户轻松查看,而不一定是为了编辑。
因此,使用 Foxit 等 PDF 操作 SDK 对于您的项目至关重要。Foxit 为所有平台和项目类型提供 SDK 和 API,以便您可以轻松地操作 PDF 文件。
在您选择的平台(Web、Windows、Android、iOS、Linux、UWP 或 Mac)上试用 Foxit PDF SDK 的先进技术。立即注册 免费三十天试用。