如何在网页中实现可编辑AcroForms PDF表单的渲染
如何在网页中实现可编辑AcroForms PDF表单的渲染
我现在正尝试在网页里展示PDF表单(不是那种依赖Acrobat嵌入的方式),希望用户能像在常规PDF阅读器中一样编辑AcroForms表单字段——比如填写文本框、勾选单选框这类操作。Firefox和Chrome自带的PDF阅读器都支持这个功能,我了解到Firefox是基于pdf.js实现的,所以我也试着用pdf.js来做,但一直找不到关于渲染文本和表单部分的清晰文档。另外react-pdf模块也没有提供PDF表单相关的使用文档,请问我该怎么实现这个需求?
我目前写出来的代码如下(用到了Mantine框架,但我觉得这和问题本身无关):
import { Button, Center, Flex, Input, Paper, Text } from "@mantine/core"; import * as pdfjslib from "pdfjs-dist"; import { useEffect, useRef, useState } from "react"; import { IconAt } from '@tabler/icons-react'; import $ from "jquery"; pdfjslib.GlobalWorkerOptions.workerSrc = new URL( 'pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url, ).toString(); async function renderCanvasLayer(pdfPage: pdfjslib.PDFPageProxy , canvas: HTMLCanvasElement , viewport: pdfjslib.PageViewport) { const ctx = canvas.getContext("2d")!; const renderTask = pdfPage.render({ canvasContext: ctx, viewport, }); return await renderTask.promise; } async function renderTextLayer(pdfPage: pdfjslib.PDFPageProxy , div: HTMLDivElement , canvas: HTMLCanvasElement , viewport: pdfjslib.PageViewport) { $(div.id) .css({ left: canvas.offsetLeft + 'px', top: canvas.offsetTop + 'px', height: canvas.height + 'px', width: canvas.width + 'px' }) .html(""); const textLayer = new pdfjslib.TextLayer({ textContentSource: await pdfPage.getTextContent(), container: div, viewport: viewport }); return await textLayer.render(); } async function loadPDFPage(pdfDocument: pdfjslib.PDFDocumentProxy , canvas: HTMLCanvasElement , div: HTMLDivElement , pageNum: number) { const pdfPage: pdfjslib.PDFPageProxy = await pdfDocument.getPage(pageNum); const viewport = pdfPage.getViewport({ scale: 1.5 }); canvas.width = viewport.width; canvas.height = viewport.height; await renderCanvasLayer(pdfPage, canvas, viewport); await renderTextLayer(pdfPage, div, canvas, viewport); }; function Page({ numPage, pdfDocument }: { numPage: number, pdfDocument: pdfjslib.PDFDocumentProxy }) { console.assert(numPage != null); const pageCanvas = useRef<HTMLCanvasElement>(null); const pageDiv = useRef<HTMLDivElement>(null); useEffect(() => { if (pageCanvas.current && pageDiv.current) { loadPDFPage(pdfDocument, pageCanvas.current, pageDiv.current, numPage); } }, [pageCanvas]); return <> <Paper shadow="xl" p="xl"> <Center> <Flex mt={10} mih={10} gap="sm" justify="center" align="center" direction="column" wrap="wrap"> <canvas ref={pageCanvas}></canvas> <div ref={pageDiv} className="select-text"></div> <Text>Seite {numPage}</Text> </Flex> </Center> </Paper > </> } function PageArea({ numPages, pdfDocument }: { numPages: number, pdfDocument: pdfjslib.PDFDocumentProxy }) { const pages = []; for (let i = 1; i != numPages; i++) { pages.push(<Page numPage={i} pdfDocument={pdfDocument}></Page>); } return <> {pages} </>; }
另外,我也接受除了pdf.js之外的其他解决方案,只要能在浏览器环境下正常工作就行。谢谢!
编辑说明:我自己做了些研究后更新了标题,这个问题主要针对Acroform PDFs,XFA格式我不太在意,毕竟它已经过时了。
备注:内容来源于stack exchange,提问作者user27018791
相关产品推荐
相关产品推荐

