Razor页面嵌入PDF后实现数字签名功能的技术问询
在Razor页面嵌入PDF实现数字签名的解决方案
问题根源
浏览器通过<object>标签内嵌的PDF默认使用浏览器内置PDF阅读器(如Chrome的PDFium、Edge的内置阅读器),这类阅读器不支持Adobe Reader/Acrobat的完整数字签名功能,所以看不到“通过输入或绘制签名签署文档”的菜单。
方案一:强制用Adobe Reader内嵌打开PDF(内网易统一配置)
通过给<object>标签添加Adobe专属的ActiveX参数,强制调用本地安装的Adobe Reader打开内嵌PDF,这样就能启用签名功能。
修改你的Razor后端代码中的embed字符串:
public IActionResult Index() { string embed = @"<object data=""{0}"" type=""application/pdf"" width=""1000px"" height=""1000px"" classid=""clsid:CA8A9780-280D-11CF-A24D-444553540000"" pluginspage=""http://get.adobe.com/reader/""> <param name=""toolbar"" value=""1""> <param name=""navpanes"" value=""1""> <param name=""scrollbar"" value=""1""> <param name=""allowPrinting"" value=""1""> <param name=""allowSigning"" value=""1""> If you are unable to view file, you can download from <a href=""{0}"">here</a> or use Adobe PDF Reader to view the file. </object>"; TempData["Embed"] = string.Format(embed, "/BlankPDFFiles/Test.pdf"); return View(); }
注意:需要内网员工的电脑都安装Adobe Reader,并且浏览器允许加载ActiveX插件(可通过组策略统一配置)。
方案二:使用PDF.js实现网页内签名(开源无依赖)
用Mozilla开源的PDF.js在网页中渲染PDF,再通过Canvas实现签名绘制,最后将签名叠加到PDF画布或修改PDF文件。
步骤:
- 下载PDF.js包,部署到内网服务器的
wwwroot/pdfjs目录下。 - 在Razor页面中添加以下代码:
<div id="pdfContainer" style="width: 1000px; height: 1000px;"></div> <button id="drawSignBtn">绘制签名</button> <button id="savePdfBtn">保存签名后的PDF</button> <script src="/pdfjs/build/pdf.js"></script> <script> // 配置PDF.js工作线程路径 pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdfjs/build/pdf.worker.js'; let pdfDoc = null; let pageCanvas = null; // 加载PDF async function loadPdf() { const pdfUrl = '/BlankPDFFiles/Test.pdf'; pdfDoc = await pdfjsLib.getDocument(pdfUrl).promise; const page = await pdfDoc.getPage(1); const viewport = page.getViewport({ scale: 1.5 }); pageCanvas = document.createElement('canvas'); pageCanvas.width = viewport.width; pageCanvas.height = viewport.height; document.getElementById('pdfContainer').appendChild(pageCanvas); await page.render({ canvasContext: pageCanvas.getContext('2d'), viewport: viewport }).promise; } // 绘制签名 let isDrawing = false; let signCanvas = null; document.getElementById('drawSignBtn').addEventListener('click', () => { signCanvas = document.createElement('canvas'); signCanvas.width = 200; signCanvas.height = 100; signCanvas.style.border = '1px solid #000'; signCanvas.style.marginTop = '10px'; document.getElementById('pdfContainer').appendChild(signCanvas); const ctx = signCanvas.getContext('2d'); ctx.lineWidth = 2; ctx.strokeStyle = '#000'; signCanvas.addEventListener('mousedown', e => { isDrawing = true; ctx.beginPath(); ctx.moveTo(e.offsetX, e.offsetY); }); signCanvas.addEventListener('mousemove', e => { if (isDrawing) { ctx.lineTo(e.offsetX, e.offsetY); ctx.stroke(); } }); signCanvas.addEventListener('mouseup', () => { isDrawing = false; // 将签名绘制到PDF页面的指定位置(示例:X=150, Y=550) const pdfCtx = pageCanvas.getContext('2d'); pdfCtx.drawImage(signCanvas, 150, pageCanvas.height - 550, 200, 100); }); }); // 保存签名后的PDF(需要额外库如pdf-lib,此处为简化示例) document.getElementById('savePdfBtn').addEventListener('click', async () => { // 若需真正修改PDF文件内容,可引入pdf-lib库实现签名嵌入 // 此处仅演示将Canvas转为图片下载 const link = document.createElement('a'); link.download = 'signed_pdf.png'; link.href = pageCanvas.toDataURL(); link.click(); }); // 初始化加载PDF loadPdf(); </script>
进阶说明:如果需要生成带合法数字证书的PDF签名,可搭配pdf-lib库,将签名和证书嵌入PDF文件,再上传到服务器。
方案三:服务器端添加签名域,用户下载签名后上传
用PDF处理库(如iTextSharp)在服务器端给PDF添加签名域,用户下载PDF后用Adobe Reader完成签名,再上传回服务器。
服务器端代码(C#):
using iTextSharp.text; using iTextSharp.text.pdf; using System.IO; public IActionResult GeneratePdfWithSignatureField() { string inputPdfPath = Path.Combine(WebRootPath, "BlankPDFFiles/Test.pdf"); string outputPdfPath = Path.Combine(WebRootPath, "BlankPDFFiles/Test_Signable.pdf"); // 读取原PDF并添加签名域 using (var reader = new PdfReader(inputPdfPath)) using (var stamper = new PdfStamper(reader, new FileStream(outputPdfPath, FileMode.Create))) { AcroFields acroFields = stamper.AcroFields; // 添加签名域:参数依次为域名、页码、左下角X/Y、右上角X/Y acroFields.AddSignature("EmployeeSignature", 1, 100, 500, 300, 600); stamper.Close(); } // 嵌入带签名域的PDF string embed = "<object data=\"{0}\" type=\"application/pdf\" width=\"1000px\" height=\"1000px\">"; embed += "If you are unable to view file, you can download from <a href=\"{0}\">here</a> to sign with Adobe Reader."; embed += "</object>"; TempData["Embed"] = string.Format(embed, "/BlankPDFFiles/Test_Signable.pdf"); return View(); }
后续流程:
- 用户下载带签名域的PDF,用Adobe Reader打开后可直接在签名域中完成签名。
- 开发文件上传功能,让用户将签名后的PDF上传回服务器存储。
内容的提问来源于stack exchange,提问作者Anjali
相关产品推荐
相关产品推荐

