You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在网页中实现可编辑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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:39:37