【问题标题】:Acrofields created with libre office are not code fillable unless I edit the pdf once使用 libre office 创建的 Acrofields 不可填充代码,除非我编辑过一次 pdf
【发布时间】:2017-11-06 12:05:46
【问题描述】:

我正在 Libre Office 中创建表单控件并将文档导出为 pdf。

尝试使用 itextsharp(即 c# 程序)设置控件(文本框)的文本只会清空该框。

但是,如果我使用 acrobat reader 打开 pdf 并编辑框中的文本,则将文档保存为可以写入该文本框的 pdf。

为什么我必须这样做?

错误再现

单击 libre office 中的工具栏图标。

在文档中拖出一个正方形。

双击该框,将其命名为 currenttime。

导出为 pdf:

c#代码

if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
    if (saveFileDialog1.ShowDialog() == DialogResult.OK)
    {
        using (var fs = new FileStream(saveFileDialog1.FileName, FileMode.Create))
        {
            var reader = new PdfReader(openFileDialog1.FileName);
            {
                using (var pdfStamper = new PdfStamper(reader, fs))
                {
                    var acroFields = pdfStamper.AcroFields;

                    acroFields.SetField("currentdate", DateTime.Now.ToString());

                    pdfStamper.FormFlattening = true;
                    pdfStamper.FreeTextFlattening = true;
                    pdfStamper.Writer.CloseStream = false;
                }
            }
            reader.Close();

            fs.Close();
        }
    }
}

编辑

这里是 pdf 的文本转储。我用“一些二进制数据”改变了一些二进制数据的位置。文本框已被赋予默认值“123”。

使用 libre office 创建后的 pdf 版本为 1.4

%PDF-1.4
some binary data
2 0 obj
<</Length 3 0 R/Filter/FlateDecode>>
stream
some binary data
endstream
endobj

3 0 obj
78
endobj

7 0 obj
<</Type/FontDescriptor/FontName/LiberationSans
/Flags 4
/FontBBox[-543 -303 1301 980]/ItalicAngle 0
/Ascent 905
/Descent -211
/CapHeight 979
/StemV 80
>>
endobj

8 0 obj
<</Type/Font/Subtype/TrueType/BaseFont/LiberationSans
/Encoding/WinAnsiEncoding
/FirstChar 32 /LastChar 255
/Widths[277 277 354 556 556 889 666 190 333 333 389 583 277 333 277 277
556 556 556 556 556 556 556 556 556 556 277 277 583 583 583 556
1015 666 666 722 722 666 610 777 722 277 500 666 556 833 722 777
666 777 722 666 610 722 666 943 666 666 610 277 277 277 469 556
333 556 556 500 556 556 277 556 556 222 222 500 222 833 556 556
556 556 333 500 277 556 500 722 500 500 500 333 259 333 583 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
277 333 556 556 556 556 259 556 333 736 370 556 583 333 736 552
399 548 333 333 333 576 537 333 333 333 365 556 833 833 833 610
666 666 666 666 666 666 1000 722 666 666 666 666 277 277 277 277
722 722 777 777 777 777 777 583 777 722 722 722 722 666 666 610
556 556 556 556 556 556 889 500 556 556 556 556 277 277 277 277
556 556 556 556 556 556 556 548 610 556 556 556 556 500 556 500
]
/FontDescriptor 7 0 R>>
endobj

5 0 obj
<</F1 8 0 R
>>
endobj

9 0 obj
<</Font 5 0 R
/ProcSet[/PDF/Text]
>>
endobj

1 0 obj
<</Type/Page/Parent 6 0 R/Resources 9 0 R/MediaBox[0 0 595 842]/Annots[
4 0 R ]
/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 2 0 R>>
endobj

6 0 obj
<</Type/Pages
/Resources 9 0 R
/MediaBox[ 0 0 595 842 ]
/Kids[ 1 0 R ]
/Count 1>>
endobj

10 0 obj
<</Type/XObject
/Subtype/Form
/BBox[0 0 82.7 23.1]
/Resources 9 0 R
/Length 18
/Filter/FlateDecode
>>
stream
some binary data
endstream
endobj

4 0 obj
<</Type/Annot/Subtype/Widget/F 4
/Rect[59.6 759.3 142.5 782.2]
/FT/Tx
/P 1 0 R
/T(currenttime)
/Ff 4096
/V <FEFF003100320033>
/DV <FEFF003100320033>
/DR<</Font 5 0 R>>
/DA(0 0 0 rg /F1 12 Tf)
/AP<<
/N 10 0 R
>>
>>
endobj

11 0 obj
<</Type/Catalog/Pages 6 0 R
/OpenAction[1 0 R /XYZ null null 0]
/Lang(sv-SE)
/AcroForm<</Fields[
4 0 R 
]/DR 9 0 R/NeedAppearances true>>
>>
endobj

12 0 obj
<</Creator<FEFF005700720069007400650072>
/Producer<FEFF004C0069006200720065004F0066006600690063006500200035002E0033>
/CreationDate(D:20170606104859+02'00')>>
endobj

xref
0 13
0000000000 65535 f 
0000001431 00000 n 
0000000019 00000 n 
0000000168 00000 n 
0000001843 00000 n 
0000001347 00000 n 
0000001590 00000 n 
0000000187 00000 n 
0000000357 00000 n 
0000001378 00000 n 
0000001688 00000 n 
0000002073 00000 n 
0000002231 00000 n 
trailer
<</Size 13/Root 11 0 R
/Info 12 0 R
/ID [ <5F5DD24A5E7FF740A8BB6B15F88EF602>
<5F5DD24A5E7FF740A8BB6B15F88EF602> ]
/DocChecksum /BFFAD3050AA9FF87945C97B9608B3C6C
>>
startxref
2406
%%EOF

在 acrobat reader 中编辑后(我将文本框的默认值从“123”更改为“12”),它将保存在 1.6 版本中,并插入一个有趣的 x:xmpmeta 信息。文档中还插入了很多空行。此时,它可以通过编程方式进行编辑。

%PDF-1.6
%âãÏÓ
7 0 obj
<</Linearized 1/L 6449/O 9/E 2599/N 1/T 6160/H [ 451 149]>>
endobj

13 0 obj
<</DecodeParms<</Columns 4/Predictor 12>>/Filter/FlateDecode/ID[<5F5DD24A5E7FF740A8BB6B15F88EF602><FAE65369E246E7409111A7D5BDED1E6F>]/Index[7 17]/Info 6 0 R/Length 52/Prev 6161/Root 8 0 R/Size 24/Type/XRef/W[1 2 1]>>stream
some binary data
endstream
endobj
startxref
0
%%EOF

23 0 obj
<</Filter/FlateDecode/I 92/Length 65/S 38/V 69>>stream
some binary data
endstream
endobj
8 0 obj
<</AcroForm<</DA(/Helv 0 Tf 0 g )/DR 22 0 R/Fields[14 0 R]>>/Lang(sv-SE)/Metadata 1 0 R/OpenAction[9 0 R/XYZ null null 0]/Pages 5 0 R/Type/Catalog>>
endobj
9 0 obj
<</Annots[14 0 R]/Contents 12 0 R/CropBox[0 0 595 842]/Group<</CS/DeviceRGB/I true/S/Transparency>>/MediaBox[0 0 595 842]/Parent 5 0 R/Resources 22 0 R/Rotate 0/Type/Page>>
endobj
10 0 obj
<</BBox[0.0 0.0 82.9 22.9]/Filter/FlateDecode/Length 68/Resources 15 0 R>>stream
some binary data
endstream
endobj
11 0 obj
<</Filter/FlateDecode/First 66/Length 1226/N 9/Type/ObjStm>>stream
some binary data
endstream
endobj
12 0 obj
<</Filter/FlateDecode/Length 78>>stream
some binary data
endstream
endobj
1 0 obj
<</Length 3146/Subtype/XML/Type/Metadata>>stream
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.4-c005 78.147326, 2012/08/23-13:03:03        ">
   <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
      <rdf:Description rdf:about=""
            xmlns:xmp="http://ns.adobe.com/xap/1.0/"
            xmlns:pdf="http://ns.adobe.com/pdf/1.3/"
            xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
            xmlns:dc="http://purl.org/dc/elements/1.1/">
         <xmp:CreateDate>2017-06-06T10:48:59+02:00</xmp:CreateDate>
         <xmp:CreatorTool>Writer</xmp:CreatorTool>
         <xmp:ModifyDate>2017-06-06T11:20:41+02:00</xmp:ModifyDate>
         <xmp:MetadataDate>2017-06-06T11:20:41+02:00</xmp:MetadataDate>
         <pdf:Producer>LibreOffice 5.3</pdf:Producer>
         <xmpMM:DocumentID>uuid:fcdf7344-18ca-44b6-934c-8d5ab8fc8ea3</xmpMM:DocumentID>
         <xmpMM:InstanceID>uuid:895fdc09-0aaa-4421-86b2-418c75f88d22</xmpMM:InstanceID>
         <dc:format>application/pdf</dc:format>
      </rdf:Description>
   </rdf:RDF>
</x:xmpmeta>





















<?xpacket end="w"?>
endstream
endobj
2 0 obj
<</Filter/FlateDecode/First 4/Length 48/N 1/Type/ObjStm>>stream
some binary data
endstream
endobj
3 0 obj
<</Filter/FlateDecode/First 4/Length 106/N 1/Type/ObjStm>>stream
some binary data
endstream
endobj
4 0 obj
<</DecodeParms<</Columns 3/Predictor 12>>/Filter/FlateDecode/ID[<5F5DD24A5E7FF740A8BB6B15F88EF602><FAE65369E246E7409111A7D5BDED1E6F>]/Info 6 0 R/Length 37/Root 8 0 R/Size 7/Type/XRef/W[1 2 0]>>stream
some binary data
endstream
endobj
startxref
116
%%EOF

编辑2

我正在将文件放在我的保管箱中。

https://www.dropbox.com/sh/5btzl9qqzua18q1/AACIjCrvNZ5cunuLj9sze-l3a?dl=0

【问题讨论】:

  • 请分享一份 PDF 样本,供大家观察问题。
  • 很遗憾,您没有分享实际的 PDF,而只是分享了一些无法用于重现问题的摘录。不过,这里已经可以看到一个重要的区别,来自 LibO 的新文件在 AcroForm 字典中将 NeedAppearances 设置为 true。根据规范,这意味着 PDF 查看器无论如何都必须创建或更新字段外观。 iText 通过在设置字段时也不创建外观来支持此标志。根据相关查看器的不同,这可能会导致问题。
  • 添加了指向这些文件的链接@mkl

标签: itext libreoffice pdfstamper


【解决方案1】:

正如评论中已经推测的那样,问题是由 Libre Office 在 AcroForm 字典中创建 NeedAppearances 设置为 true 的 PDF 引起的.此外,使用了错误的字段名称。

字段名称

在您的代码中,您设置了“currentdate”字段,而在您的示例 PDF 中,该字段被称为“currenttime”。显然你必须使用正确的字段名。

NeedAppearances 标志

这个标志告诉 PDF 查看器它应该为文档中的所有小部件注释构建外观流和外观字典。因此,iText 在填写表单域时

acroFields.SetField("currentdate", DateTime.Now.ToString());

是否为该字段创建外观 - 无论如何,任何查看器都需要构建新外观。

不幸的是表格变平

pdfStamper.FormFlattening = true;

是通过使用现有的外观实现的,并且只使用它们。由于设置字段时没有创建外观,因此其展平后的形式为空。

(严格来说,这种形式展平的实现是错误的:在这种情况下,iText 是想要使用外观的 PDF 处理器;因此,它应该在此处创建 all 外观,即使忽略现有的。)

尽管有 NeedAppearances 标志,但您可以通过告诉 iText 在表单填写期间创建外观来解决此问题:

using (var pdfStamper = new PdfStamper(reader, fs))
{
    var acroFields = pdfStamper.AcroFields;
    acroFields.GenerateAppearances = true;// <<<<<<<<<<<<<<<<<<

    acroFields.SetField("currenttime", DateTime.Now.ToString());

    pdfStamper.FormFlattening = true;
    pdfStamper.FreeTextFlattening = true;
    pdfStamper.Writer.CloseStream = false;
}

添加上面标记的行后,代码的输出包括更改后的新设置值。


此外,Libre Office 不嵌入 LiberationSans 字体。由于我没有在我的系统上安装它,我只看到点。我建议你让 LibreOffice 嵌入这样的字体,或者使用标准的 14 字体。否则,您的 PDF 将无法在多台计算机上按需要显示。

【讨论】:

  • acroFields.GenerateAppearances = true;(连同使用正确的字段名称)解决了这个问题。如何让 libre office 嵌入字体?
  • 啊,发现了,文件>属性>字体,勾选“在文档中嵌入字体”。
  • 但是,我不同意字体没有嵌入到 1_created_libre_office.pdf 中。对象 8 的字体类型为 BaseFont 名称 LiberationSans。 FirstChar 为 32,LastChar 为 255。
  • @AndersLindén 我不同意字体没有嵌入 1_created_libre_office.pdf - 字体不是嵌入,它只是 描述。如果它是嵌入的,您会发现一个包含实际 TTF 文件(或字体类型)的流。它仅被描述,其中包括编码和字符宽度等内容。
  • 如果 Libre Office 无法嵌入字体(即实际的字体文件,可能作为仅包含使用的字形的子集),这对于作为 PDF 创建者的 Libre Office 来说是一个坏兆头。 (我自己没有安装,所以我不知道。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-16
  • 1970-01-01
  • 2014-09-03
  • 2018-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多