【问题标题】:Flatten FDF / XFDF forms to PDF in PHP with utf-8 characters使用 utf-8 字符在 PHP 中将 FDF / XFDF 表单展平为 PDF
【发布时间】:2011-04-27 18:15:51
【问题描述】:

我的场景:

  • 带有表单域的 PDF 模板:template.pdf
  • 包含要填写的数据的 XFDF 文件:fieldData.xfdf

现在我需要将这些文件合并和展平。 pdftk 在 php 中轻松完成这项工作:

exec("pdftk template.pdf fill_form fieldData.xfdf output flatFile.pdf flatten");

不幸的是,这不适用于完整的 utf-8 支持。 例如:西里尔字母和希腊字母被打乱。我为此使用了 Arial,带有 unicode 字符集。

  • 如何实现扁平化我的 unicode 文件?
  • 还有其他支持 unicode 的 pdf 工具吗?
  • pdftk 是否有我缺少的 unicode 开关?

编辑 1:由于这个问题已经超过 9 个月没有得到解决,我决定为它开始赏金。如果有赞助 pdftk 中的功能或错误修复的选项,我很乐意捐赠。

编辑 2:我不再从事这个项目,所以我无法验证新的答案。如果有人有类似的问题,我很高兴他们能对我做出回应。

【问题讨论】:

标签: pdf utf-8 flatten pdftk xfdf


【解决方案1】:

我发现使用 Jon 的模板但使用 DomDocument 为我处理了数字编码并且效果很好。我的细微变化如下:

$xml = new DOMDocument( '1.0', 'UTF-8' );

$rootNode = $xml->createElement( 'xfdf' );
$rootNode->setAttribute( 'xmlns', 'http://ns.adobe.com/xfdf/' );
$rootNode->setAttribute( 'xml:space', 'preserve' );
$xml->appendChild( $rootNode );

$fieldsNode = $xml->createElement( 'fields' );
$rootNode->appendChild( $fieldsNode );

foreach ( $fields as $field => $value )
{
    $fieldNode = $xml->createElement( 'field' );
    $fieldNode->setAttribute( 'name', $field );
    $fieldsNode->appendChild( $fieldNode );

    $valueNode = $xml->createElement( 'value' );
    $valueNode->appendChild( $xml->createTextNode( $value ) );
    $fieldNode->appendChild( $valueNode );
}

$xml->save( $file );

【讨论】:

    【解决方案2】:

    您可以试试http://www.adobe.com/products/livecycle/designer/ 的试用版,看看它会生成哪些 PDF 文件。

    您可以尝试的另一个商业软件是http://www.appligent.com/fdfmerge。请参阅http://146.145.110.1/docs/userguide/FDFMergeUserGuide.pdf 中的第 16 页,了解它如何使用 UTF-8 处理 xFDF。

    我还查看了 FDF 规范 http://partners.adobe.com/public/developer/en/xml/xfdf_2.0.pdf 第 12 页指出:

    Although XFDF is encoded in UTF-8, double byte characters are encoded as character references when 
    exported from Acrobat. 
    For example, the Japanese double byte characters ,  , and  are exported to XFDF using 
    three character references. Here is an example of double byte characters in a form field: 
      ...
    <fields>  
      <field name="Text1"> 
         <value>Here are 3 UTF-8 double byte  
            characters: &#x3042;&#x3044;&#x3046;
    </value>  
      </field>  
    </fields> ... 
    

    我浏览了 pdftk-1.44-dist/java/com/lowagie/text/pdf/XfdfReader.java。它似乎没有对输入做任何特别的事情。

    当您将奇怪的字符编码为 xFDF 输入中的字符引用时,也许 pdftk 会做您想做的事情。

    【讨论】:

    • 谢谢,我稍后会尝试那个字符引用的东西。
    • 不幸的是,我安装的代码库损坏了。这只是意味着要延迟几天。
    • 很遗憾没有——但我承认我没有花太多时间在这上面……所以我会再试一次。
    【解决方案3】:

    在 Win7 机器上使用 pdftk 1.44 我遇到了与 xfdf 文件相同的问题,而 fdf 工作正常。我制作了一个没有任何特殊字符(只有 ANSI)的 xfdf 文件,但 pdftk 再次崩溃。我给开发者发了邮件。很遗憾,直到现在都没有答案。

    【讨论】:

      【解决方案4】:

      不幸的是,UTF-8 字符编码不适用于源 .xfdf 文件中非 ASCII 字符的十进制或十六进制引用。 PDFTK v. 1.44。

      【解决方案5】:

      我在这方面取得了一些进展。从http://koivi.com/fill-pdf-form-fields/ 的代码开始,我修改了值编码以输出ascii 范围之外的任何字符的数字代码。

      现在有了pitulski的特殊字符串:

      Poznań Śródmieście Ćwiartka Ósma 输出 Pozna ródmiecie wiartka Ósma 并叠加了一些盒子形状

      ęóąśłżźćńĘÓĄŚŁŻŹĆŃ 输出具有更多盒子形状的óÓ。我认为可能是盒子形状是我的服务器无法识别的字符。

      我尝试了一些法语字符:ùûüÿ€’“”«»àâæçéèêëïôœÙÛÜŸÀÂÆÇÉÈÊËÏÎÔ,它们都出来了,但其中一些重叠。

      --edit-- 我只是尝试将这些手动输入到表单中,并得到相同的结果减去框形状(使用 Evince)。然后我尝试使用不同的表单(由其他人创建) - 输入ęóąśłżźćńĘÓĄŚŁŻŹĆŃ 后,显示ółÓŁ。看起来这取决于文档的嵌入字体中包含哪些字符。

      /*
      KOIVI HTML Form to FDF Parser for PHP (C) 2004 Justin Koivisto
      Version 1.2.?
      Last Modified: 2013/01/17 - Jon Hulka(jon dot hulka at gmail dot com)
        - changed character encoding, all non-ascii characters get encoded as numeric character references
      
          This library is free software; you can redistribute it and/or modify it
          under the terms of the GNU Lesser General Public License as published by
          the Free Software Foundation; either version 2.1 of the License, or (at
          your option) any later version.
      
          This library is distributed in the hope that it will be useful, but
          WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
          or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
          License for more details.
      
          You should have received a copy of the GNU Lesser General Public License
          along with this library; if not, write to the Free Software Foundation,
          Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
      
          Full license agreement notice can be found in the LICENSE file contained
          within this distribution package.
      
          Justin Koivisto
          justin dot koivisto at gmail dot com
          http://koivi.com
      */
      
      /**
       * createXFDF
       * 
       * Tales values passed via associative array and generates XFDF file format
       * with that data for the pdf address sullpiled.
       * 
       * @param string $file The pdf file - url or file path accepted
       * @param array $info data to use in key/value pairs no more than 2 dimensions
       * @param string $enc default UTF-8, match server output: default_charset in php.ini
       * @return string The XFDF data for acrobat reader to use in the pdf form file
       */
      function createXFDF($file,$info,$enc='UTF-8'){
          $data=
      '<?xml version="1.0" encoding="'.$enc.'"?>
      <xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
          <fields>';
          foreach($info as $field => $val){
              $data.='
              <field name="'.$field.'">';
              if(is_array($val)){
                  foreach($val as $opt)
      //2013.01.17 - Jon Hulka - all non-ascii characters get character references
                  $data.='
                  <value>'.mb_encode_numericentity(htmlspecialchars($opt),array(0x0080, 0xffff, 0, 0xffff), 'UTF-8').'</value>';
      //                $data.='<value>'.htmlentities($opt,ENT_COMPAT,$enc).'</value>'."\n";
              }else{
                  $data.='
                  <value>'.mb_encode_numericentity(htmlspecialchars($val),array(0x0080, 0xffff, 0, 0xffff), 'UTF-8').'</value>';
      //            $data.='<value>'.htmlentities($val,ENT_COMPAT,$enc).'</value>'."\n";
              }
              $data.='
              </field>';
          }
          $data.='
          </fields>
          <ids original="'.md5($file).'" modified="'.time().'" />
          <f href="'.$file.'" />
      </xfdf>';
          return $data;
      }
      

      【讨论】:

        【解决方案6】:

        虽然 pdftk 在 FDF 文件中似乎不支持 UTF-8,但我发现使用

        iconv -f utf-8 -t ISO_8859-1
        

        在将该 FDF 文件转换为 ISO-Latin-1 的管道中,那么至少在 Latin-1 代码页中的那些字符仍将被正确表示。

        【讨论】:

          【解决方案7】:

          什么PDFTK的版本? 我用波兰语字符(utf-8)尝试了同样的事情。

          不适合我。

          pdftk.exe、libiconv2.dll 来自:http://www.pdflabs.com/docs/install-pdftk/

          Windows 7、cmd、file.pdf + file.fdf -> new.pdf

          pdftk file.pdf fill_form file.xfdf 输出 new.pdf 展平

          Unhandled Java Exception:
          java.lang.NoClassDefFoundError: gnu.gcj.convert.Input_UTF8 not found in [file:.\, core:/]
             at 0x005a3abe (Unknown Source)
             at 0x005a3fb2 (Unknown Source)
             at 0x006119f4 (Unknown Source)
             at 0x00649ee4 (Unknown Source)
             at 0x005b4c44 (Unknown Source)
             at 0x005470a9 (Unknown Source)
             at 0x00549c52 (Unknown Source)
             at 0x0059d348 (Unknown Source)
             at 0x007323c9 (Unknown Source)
             at 0x0054715a (Unknown Source)
             at 0x00562349 (Unknown Source)
          

          但是,对于具有相同内容的 FDF 文件,它可以正常工作。 但是new.PDF中的字符不好。

          pdftk file.pdf fill_form file.fdf 输出 new.pdf 展平

          ---FDF---

          %FDF-1.2
          %âãÏÓ
          1 0 obj<</FDF<</F(file.pdf)
          /Fields[
          <</T(Miejsce)/V(666 Poznań Śródmieście Ćwiartka Ósma)>>
          <</T(Nr)/V(ęóąśłżźćńĘÓĄŚŁŻŹĆŃ)>>
          ]>>>>
          endobj
          trailer
          <</Root 1 0 R>>
          %%EOF
          

          ---XFDF---

          <?xml version="1.0" encoding="UTF-8"?>
          <xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
          <f href="file.pdf"/>
          <fields>
          <field name="Miejsce">
          <value>666 Poznań Śródmieście Ćwiartka Ósma</value>
          </field>
          <field name="Nr">
          <value>ęóąśłżźćńĘÓĄŚŁŻŹĆŃ</value>
          </field>
          </fields>
          </xfdf>
          

          ---PDF---

          Miejsce: 666 PoznaÅ— ÅıródmieÅłcie ăwiartka Ãfisma
          Nr: ÄŽÃ³Ä–ÅłÅ‡Å¼ÅºÄ⁄Å—ÄŸÃfiÄ—ÅıņŻŹăÅ
          

          【讨论】:

          • 情况大致相同。我尝试使用版本 1.41-3 和 1.43。如我所见,1.44 自 2010 年 10 月 28 日起发布。我会试一试。
          • 我也遇到了与上述 uwith fdf 相同的异常。
          【解决方案8】:

          您可以通过使用 \ddd 提供八进制的 unicode 代码来引入 utf-8 字符

          【讨论】:

            【解决方案9】:

            为了解决这个问题,我写了 PdfFormFillerUTF-8:http://sourceforge.net/projects/pdfformfiller2/

            【讨论】:

            • 链接不是答案。关于 SO 的答案预计是独立的。请review this meta question 并为您的问题添加足够的细节,使其不完全依赖外部链接。也许你应该添加一个代码示例来展示这个库将如何解决问题?
            【解决方案10】:

            有一个 pdftk 工具的直接替代品

            Mcpdfhttps://github.com/m-click/mcpdf

            在填写表单时解决了 unicode 问题。适合我使用 CP1250 字符(中欧)。

            来自项目页面:

            以下命令将表单数据从 DATA.xfdf 填充到 FORM.pdf 并将结果写入 RESULT.pdf。它还将文档展平为 防止进一步编辑:

            java -jar mcpdf.jar FORM.pdf fill_form - output - flatten < DATA.xfdf > RESULT.pdf
            

            这完全对应于通常的 PDFtk 命令:

            pdftk FORM.pdf fill_form - output - flatten < DATA.xfdf > RESULT.pdf
            

            请注意,您需要安装 JRE。

            【讨论】:

            • gitrepo 不提供示例 pdf 文件。对于我的 pdf 文件,即使对于他们使用单词“Łódź”的用例也不起作用(缺少一些字符。我尝试了不同 pdf 形式的不同字符。是的,我也尝试从 LibreOffice 生成表单)。在我的测试以及others 中,它根本不适用于俄语字符。 mcpdf 可能适用于作者的管道,除此之外,它似乎被破坏了。虽然环绕 iText 的想法是合理的。
            【解决方案11】:

            我已经设法通过创建一个带有 utf-8 编码的 xfdf 文件使其与 pdftk 一起使用。

            尝试了几次,但使其正常工作的是添加“need_appearances”

            这是一个例子:

            pdftk source.pdf fill_form data.xfdf output output.pdf need_appearances
            

            【讨论】:

              【解决方案12】:

              这个问题我解决了很久,终于找到了解决办法!

              那么,让我们开始吧。

              1. 下载安装最新版pdftk
              # PDFTK
              RUN apk add openjdk8 \
                  && cd /tmp \
                  && wget https://gitlab.com/pdftk-java/pdftk/-/jobs/1507074845/artifacts/raw/build/libs/pdftk-all.jar \
                  && mv pdftk-all.jar pdftk.jar \
                  && echo '#!/usr/bin/env bash' > pdftk \
                  && echo 'java -jar "$0.jar" "$@"' >> pdftk \
                  && chmod 775 pdftk* \
                  && mv pdftk* /usr/local/bin \
                  && pdftk -version
              
              1. 在 Adob​​e Acrobat Reader 中打开您的 PDF 表单并查看字段选项,您需要检测字体,例如 Helvetica,下载此字体。
              2. 使用flatten 选项填写表格
              /usr/local/bin/pdftk A=form.pdf fill_form xfdf.xml output out.pdf drop_xfa need_appearances flatten replacement_font /path/to/font/HelveticaRegular.ttf
              

              xfdf.xml 示例:

              <?xml version="1.0" encoding="UTF-8"?>
              <xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
                  <fields>
                      <field name="Check Box 136">
                          <value>Your value | Значение (Cyrillic)</value>
                      </field>
                  </fields>
              </xfdf>
              

              享受:)

              【讨论】:

                【解决方案13】:

                pdftk 支持 UTF-16BE 编码。从 UTF-8 转换为 UTF-16BE 并不难。

                见:Weird characters when filling PDF with PDFTk

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2013-06-16
                  • 1970-01-01
                  • 2011-08-01
                  • 1970-01-01
                  • 2017-09-26
                  • 2015-06-05
                  • 2013-04-09
                  • 1970-01-01
                  相关资源
                  最近更新 更多