通过使用PdfCopy从模板复制PDF来创建PDF(丢失数据)

时间:2014-08-29 14:13:32

标签: c# pdf copy itextsharp

我尝试使用PdfCopy创建基于另一个的新pdf文件。 生成过程中一切正常,生成的文件可以在我的桌面上打开而没有任何问题,但文件似乎已损坏,我必须使用的服务不能接受:

  

调用'签名&#39>时出现SignService错误,可能是由于文件格式错误造成的。

我注意到生成的pdf总是比原始模板更精确,因此我将模板版本与生成的模板进行了比较。丢失数据有一些重要部分,尤其是一大堆xml。我想PdfCopy不会复制我原来的每一个pdf,但我无法弄清楚我错过了什么。

这是我的方法:

byte[] completedDocument = null;
string originalUri = Path.Combine(this.PdfPath, pdfName);
string generatedUri = Path.Combine(this.PdfGeneratedPath, generatedPdfName);

        using(MemoryStream streamCompleted = new MemoryStream())
        {
            using(Document doc = new Document())
            {
                PdfCopy copy = new PdfCopy(doc, streamCompleted);

                copy.PdfVersion = PdfWriter.VERSION_1_6;
                doc.Open();
                copy.Open();

                byte[] mergedDocument = null;
                PdfReader pdfReader = new PdfReader(originalUri);
                int pdfPageNumber = pdfReader.NumberOfPages;

                using(MemoryStream streamTemplate = new MemoryStream())
                {
                    using (PdfStamper pdfStamper = new PdfStamper(pdfReader, streamTemplate))
                    {
                        AcroFields acrofields = pdfStamper.AcroFields;

                        foreach (KeyValuePair<string, AcroFields.Item> field in acrofields.Fields)
                        {
                            string data;
                            if (pdfFieldsValues.TryGetValue(field.Key, out data))
                            {
                                if (data == null)
                                {
                                    data = string.Empty;
                                }

                                acrofields.SetField(field.Key, data);
                            }
                        }

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

                    mergedDocument = streamTemplate.ToArray();
                }

                pdfReader = new PdfReader(mergedDocument);

                for (int page = 1; page <= pdfPageNumber; page++)
                {
                    if (!excludedPages.Any(s => s == page))
                    {
                        copy.AddPage(copy.GetImportedPage(pdfReader, page));
                    }
                }

                doc.Close();
                copy.Close();
            }

            completedDocument = streamCompleted.ToArray();
        }

        File.WriteAllBytes(generatedUri, completedDocument);

我尝试上传&#34; mergedDocument&#34;而不是&#34; completedDocument&#34;我的服务接受了它,所以我很确定它与这部分有关:

for (int page = 1; page <= pdfPageNumber; page++)
{
    if (!excludedPages.Any(s => s == page))
    {
        copy.AddPage(copy.GetImportedPage(pdfReader, page));
    }
}

或pdfCopy init

1 个答案:

答案 0 :(得分:0)

您从表单开始。您填写表格并将其展平。通过展平它,你故意抛弃所有交互性。我很惊讶您对文件越来越小感到惊讶:您正在丢弃表单基础架构!

然后,您将展平文件上传到我们未知的某项服务。这项服务抱怨:

  

调用&#39;签名&#39>时出现SignService错误,可能是由于文件格式错误造成的。

由于我们不知道您在谈论哪种服务,我们只能猜测。有根据的猜测是原始表单包含需要由签名服务签名的签名字段。

显然这个领域已经消失了:你把表格弄平了!我可能错了,但我认为该服务还试图读取你填写的字段,但那不会是当你抛弃所有交互性时可能。请删除以下一行:

pdfStamper.FormFlattening = true;

然后是克里斯&#39;评论:您似乎正在使用PdfCopy。如果您使用的是旧版iTextSharp(在iText 5.5.1之前),您不应期望保留该表单。如果您使用的是最新版本,则应指示PdfCopy保留表单(但缺少该行)。您不需要询问&#39;我如何保留表单?&#39; 因为您不应该使用PdfCopy

您只需要PdfStamper。您已使用PdfStamper填写字段,现在您还可以使用selectPages()方法选择要保留的页面(或排除要删除的页面)。

最后,目前还不清楚你写作时的意思:

  

缺少数据的一些重要部分,尤其是一大堆xml。

您是说该表单不是纯AcroForm,但它还包含XFA流吗?如果是这样,那么你绝对不能使用PdfCopy