Node.js使用PFX文件签名PDF后可视化签章不显示的问题求助
Node.js使用PFX文件签名PDF后可视化签章不显示的问题求助
最近接了个任务,需要用Node.js结合PFX文件给PDF做数字签名。现在签名功能已经跑通了,也能在PDF里找到指定标记位置添加签名占位符,但遇到了一个很棘手的问题:签名在视觉上完全没有显示出来。
具体情况是这样的:PDF里的签名位置是个空白框,鼠标悬停上去能看到签名有效性的提示,但框里啥都没有——既没有常见的✔对勾、✖叉号,也没有我设置的签名人名称、原因这些文字信息,完全不像官方/政府文档里那种一目了然的签章效果。点击这个空白框倒是能弹出签名有效性的对话框,证明签名是有效的,但视觉上就是一片空白,完全达不到需求里的效果。
我是通过在PDF中查找标记文本DigiSign来定位签名位置的,然后用pdf-lib添加占位符,再用@signpdf的工具完成签名。下面是我的完整代码,麻烦各位大佬帮忙看看哪里出了问题,怎么才能让可视化的签章正常显示出来?
const express = require('express'); const { PDFDocument, rgb, StandardFonts, PDFName, PDFNumber } = require('pdf-lib'); const signpdf = require('@signpdf/signpdf').default; const { P12Signer } = require('@signpdf/signer-p12'); const { pdflibAddPlaceholder } = require('@signpdf/placeholder-pdf-lib'); const pdfjsLib = require('pdfjs-dist/legacy/build/pdf.mjs'); const app = express(); app.use(express.json({ limit: '50mb' })); async function findMarkerCoords(pdfBuffer, marker) { const loadingTask = pdfjsLib.getDocument({ data: new Uint8Array(pdfBuffer) }); const pdf = await loadingTask.promise; const numPages = pdf.numPages; for (let pageIndex = 0; pageIndex < numPages; pageIndex++) { const page = await pdf.getPage(pageIndex + 1); const textContent = await page.getTextContent(); for (const item of textContent.items) { if (item.str && item.str.includes(marker)) { return { pageIndex, x: item.transform[4], y: item.transform[5] }; } } } throw new Error(`Marker "${marker}" not found in any page.`); } app.post('/sign', async (req, res) => { try { const { pdf, pfx, password } = req.body; if (!pdf || !pfx || !password) { return res.status(400).json({ status: 'error', message: 'Missing pdf, pfx, or password.' }); } const pdfBuffer = Buffer.from(pdf, 'base64'); const pfxBuffer = Buffer.from(pfx, 'base64'); const marker = 'DigiSign'; // Get coordinates of the marker text const { pageIndex, x, y } = await findMarkerCoords(pdfBuffer, marker); // Load PDF with pdf-lib const pdfDoc = await PDFDocument.load(pdfBuffer); const pdfPage = pdfDoc.getPages()[pageIndex]; const font = await pdfDoc.embedFont(StandardFonts.Helvetica); const fontSize = 10; // Draw the signature appearance box const sigX = x; const sigY = y; const sigWidth = 180; const sigHeight = 60; const pages = pdfDoc.getPages(); for (const page of pages) { const annots = page.node.Annots(); if (annots) { const annotsArray = annots.asArray(); for (const annotRef of annotsArray) { const annot = pdfDoc.context.lookup(annotRef); annot.set(PDFName.of('F'), PDFNumber.of(4)); annot.set(PDFName.of('Type'),PDFName.of('Annot')); annot.set(PDFName.of('Subtype'),PDFName.of('Widget')); annot.set(PDFName.of('FT'),PDFName.of('Sig')); const rect = pdfDoc.context.obj([sigX,sigY,sigX + sigWidth , sigY + sigHeight]); annot.set(PDFName.of('Rect'),rect); } } } // Add visible signature placeholder pdflibAddPlaceholder({ pdfDoc : pdfDoc, pdfPage : pdfPage, reason: 'Signed for approval', contactInfo: 'xyz@gmail.com', name: 'Aditya Garg', location: 'India', signingTime: new Date(), signatureLength: 12000, widgetRect: [sigX, sigY, sigX + sigWidth, sigY + sigHeight], }); // Make signature annotation visible const pdfWithPlaceholder = await pdfDoc.save({ useObjectStreams: false }); const signer = new P12Signer(pfxBuffer, { passphrase: password }); const signedPdf = await signpdf.sign(Buffer.from(pdfWithPlaceholder), signer); return res.json({ status: 'success', signedPdf: signedPdf.toString('base64') }); } catch (err) { console.error('Signing failed:', err); return res.status(500).json({ status: 'error', message: err.message }); } }); app.listen(3000, () => { console.log('✅ Digital Signature Server running at http://localhost:3000'); });
内容来源于stack exchange
相关产品推荐
相关产品推荐

