使用PdfCopy从模板复制PDF(数据丢失)

本文关键字:数据 PDF 复制 PdfCopy 使用 | 更新日期: 2023-09-27 18:20:09

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

调用"sign"时发生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);

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

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

或者pdfCopy init

使用PdfCopy从模板复制PDF(数据丢失)

你从一个表单开始。你填写表单并将其压平。通过压平它,你故意放弃了所有的交互性。我很惊讶你对文件变小感到惊讶:你正在扔掉表单基础结构!

然后,您将扁平文件上传到我们未知的某个服务。该服务投诉:

调用"sign"时发生SignService错误,可能是由错误的文件格式引起的。

由于我们不知道你说的是哪项服务,我们只能猜测。一个有根据的猜测是,原始表单包含一个需要由签名服务签名的签名字段。

很明显,这个字段已经不见了:你把表单弄平了我可能错了,但我认为服务也会尝试读取您填写的字段,但这也不可能,因为您放弃了所有的交互性。请删除以下行:

pdfStamper.FormFlattening = true;

然后是Chris的评论:看起来你在使用PdfCopy。如果您使用的是旧版本的iTextSharp(iText5.5.1之前),则不应期望保留该表单。如果使用的是最新版本,则应指示PdfCopy保留该表单(但缺少该行)。你不需要问"我如何保存表单?"因为无论如何都不应该使用PdfCopy

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

最后,当你写时,还不清楚你的意思是什么

缺少的数据有很大一部分,尤其是一大堆xml。

你是说这个表单不是一个纯AcroForm,而是说它还包含一个XFA流?如果是这样,那么你肯定不能使用PdfCopy