尝试使用 pdf-lib 用来自服务器的 JSON 数据填充 pdf 表单字段客户端,几个问题

问题描述

我正在研究使用 pdf-lib 库表单来处理 pdf 表单。软件包位于此处:pdf-lib

编辑这个问题,只包含一个在获得正确的脚本标签库后至少部分工作的代码片段。我有一个示例表单,在此处的 url 中填充了表单字段:

Sample form

把一些最有效的代码在这里。示例的网址在上面,虚拟数据也在这里JSON DATA

Snippet 无法工作,因为它无法调用外部 url,但在本地主机上设置很容易。我想要做的第一部分几乎可以工作,即使用 JSON 文件中的数据或稍后从数据库填充表单字段。

我不确定单选按钮和复选框是否正常工作,因为我看到许多单选按钮的错误如下。可能只是正确设置,但我似乎不知道如何设置它们。我曾尝试将选项设置为“是”、“否”、“1”、“0”(有时“2”表示“NA”),但仍有一些问题。

`option` must be one of '1' or 'Yes',but was actually ' 0'
`option` must be one of '1' or 'Yes',but was actually '0'
`option` must be one of '1' or 'Yes' or 'Yes',but was actually '2'

从长远来看,我希望将表单扁平化,并可能将表单数据提交到数据库和/或提交已填写表单的 PDF 版本以上传文件系统。需要先让第一部分工作。

$("#pdf").on("load",function(e) {
    autoResize($(this));
});

function autoResize(iframe) {
    //     iframe.height($(iframe).contents().find('html').height());
    iframe.height("1650px");
    iframe.width("1275px");
    iframe.show();
}


$(document).ready(function() {


    console.log( "ready!" );

    $('#preauthform').change(function () {
    
        decoded = JSON.parse($(this).val());
        var formurl = decoded.formurl;
        // Fetch the formfield data from the backend,JSON,will probably want to pass params to dynamically create the data to be returned.
        // Using raw JSON for Now,Could use DB and json_encode() the data in PHP.
        $.ajax({
            type: "POST",url: decoded.dataurl,dataType: "json",data: {},})
        .done(function(data,textStatus,jqXHR) {
            RenderData(formurl,data);
        });

});

    
  const { PDFDocument,PDFDocumentWriter,rgb } = PDFLib
  
  

  async function RenderData(form,fields) {
  
  
  
    const url_file = form
    const formPdfBytes = await fetch(url_file).then(res => res.arrayBuffer())
    const PDFDocument = PDFLib.PDFDocument
    // Load a PDFDocument from the existing PDF bytes
    const pdfDoc = await PDFDocument.load(formPdfBytes)
    
    // Get the form containing all the fields
    var formfields = pdfDoc.getForm()

    // Register the `fontkit` instance
    // pdfDoc.registerFontkit(fontkit)

    // Embed our custom font in the document
    // const customFont = await pdfDoc.embedFont(fontBytes)
    // Iterate through the form data and fill based on type.
    $.each(fields,function(fieldname,fielddata) {
    
        console.log(fieldname);
        console.log(fielddata);
        switch(fielddata.type) {
            case "text":
                try {
                formfields.getTextField(fieldname).setText(fielddata.value);
                }
                catch(err) {
                    console.log(err.message);
                }
                break;
            case "radio":
                try {
                formfields.geTradioGroup(fieldname).select(fielddata.value);
                console.log("set radio to " + fielddata.value);
                }
                catch(err) {
                    console.log(err.message);
                }
                break;                
            case "check":
                try {
                if (fielddata.value == "0") {
                    formfields.getCheckBox(fieldname).uncheck();
                }
                else formfields.getCheckBox(fieldname).check();
                console.log("set check to " + fielddata.value);
                }
                catch(err) {
                    console.log(err.message);
                }
                break; 
            default:
        }
        
    });
    
    const pdfBytes = await pdfDoc.saveAsBase64({ dataUri: true })
//     console.log(pdfBytes)
//     window.open(pdfBytes,'_blank');
    document.getElementById('pdf').src = pdfBytes;

    //download(pdfBytes,"pdf-lib_creation_example.pdf","application/pdf");

    }

});
<html>
  <head>
    <Meta charset="utf-8" />

<Meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<Meta name="description" content="">
<Meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@pdf-lib/fontkit/dist/fontkit.umd.js"></script>
<script src="https://unpkg.com/downloadjs@1.4.7"></script>


  </head>

  <body>
    <form>
    <select id = "preauthform">
    <option value = "">Select</option>
    <option value = '{"formurl":"/pdf-lib/preauths/MRI-Windows.pdf","dataurl":"/pdf-lib/preauths/MRI.json.PHP"}'>MRI-Windows.pdf</option>
    <option value = ""></option>
    <option value = ""></option>
    <option value = ""></option>
    <option value = ""></option>
    </select>
    
    <iframe style = "display:none;border:0;margin:5px;padding:5px;" src="" id="pdf"></iframe></body></html>

这里还有一个更新版本,它可以完成我正在寻找的大部分内容,除了在保留数据的同时展平表单。不知道是什么问题。展望未来,还想实施:

  1. 将表单数据提交到后端。
  2. 将扁平化和填充的 PDF 提交到后端

当前设置的原始 HTML。我补充说:

$("[src='https://unpkg.com/pdf-lib@1.16.0/dist/pdf-lib.min.js']").on("load",function(e) {

因为在 JS 执行时,库准备就绪存在问题。这似乎解决了这个问题。

<!-- Adapated from https://github.com/Hopding/pdf-lib/issues/457 -->
<script src="https://unpkg.com/pdf-lib@1.16.0/dist/pdf-lib.min.js">
</script>
<script src="https://cdn.jsdelivr.net/npm/@pdf-lib/fontkit/dist/fontkit.umd.js">
</script>
<script src="https://unpkg.com//downloadjs@1.4.7/download.js">
</script>
<style> .modal-dialog {
        max-width:100%;
    }
    #flatten {
    
        position: absolute;
        top: 0;
        right: 0;
        left: 0;
        margin: auto;
    }
    #saveform {
    
        position: absolute;
        top: 20px;
        right: 0;
        left: 0;
        margin: auto;
    }
</style>
<h5>
    Use browser to Print or Download 
</h5>
<button class="uibuttonsmallred pdf-lib" id="flatten">Flatten</button>
<button class="uibuttonsmallred pdf-lib" id="saveform">Save</button>
<iframe style="display:none;border:0;margin:5px;padding:5px;" src="" id="pdf"></iframe>
<script nonce="<?PHP echo $_SESSION['nonce'] ?>">

    var pdfDoc;
    var pdfBytes;
    
    
  $("[src='https://unpkg.com/pdf-lib@1.16.0/dist/pdf-lib.min.js']").on("load",function(e) {
        
    const { PDFDocument,rgb } = PDFLib;
    
      RenderData('<?PHP echo $data["formurl"] ?>',<?PHP echo $data['formdata'] ?>,'<?PHP echo $data["QRCode"] ?>' );
      console.log( "ready!" );
    
      async function RenderData(formurl,fields,QRCode) {
      
      const formPdfBytes = await fetch(formurl,{
        headers: {
        'csrf-token': '<?PHP echo Csrf::maketoken() ?>','nonce': '<?PHP echo $_SESSION["nonce"] ?>'
        }
      })
        .then(res => res.arrayBuffer())
        const PDFDocument = PDFLib.PDFDocument
        // Load a PDFDocument from the existing PDF bytes
        pdfDoc = await PDFDocument.load(formPdfBytes)
        const  QRCodeEmbed = await pdfDoc.embedpng(QRCode)
        const page = pdfDoc.getPage(0)
        page.drawImage(QRCodeEmbed,{
            width: 100,height: 100,y: 692,x:280
      })
      console.log(page.getSize())
        // Get the form containing all the fields
        formfields = pdfDoc.getForm()
    
        // Register the `fontkit` instance
        // pdfDoc.registerFontkit(fontkit)
    
        // Embed our custom font in the document
        // const customFont = await pdfDoc.embedFont(fontBytes)
        // Iterate through the form data and fill based on type.
        // formfields.getTextField('QRCode').setText(QRCodeEmbed)
        
        $.each(fields,fielddata) {
        
            console.log(fieldname);
            console.log(fielddata);
            switch(fielddata.type) {
                case "text":
                    try {
                    formfields.getTextField(fieldname).setText(fielddata.value);
                    }
                    catch(err) {
                        //console.log(err.message);
                    }
                    break;
                case "radio":
                    try {
                    let button = formfields.geTradioGroup(fieldname);
                    button.select(fielddata.value);
                    //console.log("set radio to " + fielddata.value);
                    }
                    catch(err) {
                        //console.log(err.message);
                    }
                    break;                
                case "check":
                    try {
                    if (fielddata.value == "0") {
                        formfields.getCheckBox(fieldname).uncheck();
                    }
                    else formfields.getCheckBox(fieldname).check();
                    //console.log("set check to " + fielddata.value);
                    }
                    catch(err) {
                        //console.log(err.message);
                    }
                    break; 
                default:
            }
            
        });
    
        pdfBytes = await pdfDoc.saveAsBase64({ dataUri: true })
        document.getElementById('pdf').src = pdfBytes;
        
    $("#flatten").on("click",function(e) {
    
      formfields.flatten();
        async function Flatten() {
        const base64DataUri = await pdfDoc.saveAsBase64({ dataUri: true })
        document.getElementById('pdf').src = base64DataUri
        download(document.getElementById('pdf').src,"application/pdf");
        }
      Flatten()    
    });
    
    }
    
    });   
    
    
    
      $("#pdf").on("load",function(e) {
        autoResize($(this));
    });
    
    function autoResize(iframe) {
    
        //     iframe.height($(iframe).contents().find('html').height());
        iframe.height("1650px");
        iframe.width("1275px");
        iframe.show();
    }
    
        
    
    $("#saveform").on("click",function(e) {
        alert ("Submit the Embedded PDF to BackEnd Server");
    });
</script>

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)