iTextSharp 5生成的PDF文档与AdobeReader兼容

iTextSharp 5生成的PDF文档与AdobeReader兼容,itext,adobe-reader,Itext,Adobe Reader,我正在使用iText5生成一些报告 打开生成的.PDF文件,大多数PDF阅读器看起来和实际上都很好 但是,当我使用AdobeReader(DC)打开PDF时,它会询问我是否要在关闭时保存更改。虽然我没有改变什么 点击“取消”可以确保消息窗口消失,但点击“保存”会导致文件实际缩小 现在那里发生了什么?为什么?如何禁用它 应用程序的用户很可能也会使用AdobeReader 我不希望他们在任何时候打开报表时都看到“保存”对话框 这是我的基本报告课 public abstract class Base

我正在使用iText5生成一些报告

打开生成的.PDF文件,大多数PDF阅读器看起来和实际上都很好

但是,当我使用AdobeReader(DC)打开PDF时,它会询问我是否要在关闭时保存更改。虽然我没有改变什么

点击“取消”可以确保消息窗口消失,但点击“保存”会导致文件实际缩小

现在那里发生了什么?为什么?如何禁用它

应用程序的用户很可能也会使用AdobeReader

我不希望他们在任何时候打开报表时都看到“保存”对话框

这是我的基本报告课

public abstract class BaseReport : PdfPageEventHelper
{
    protected const string SPACE = " ";
    protected const string COLON = ":";
    protected static string NEWLINE = Environment.NewLine;
    protected Document document;
    protected PdfTemplate footerTemplate;
    protected PdfContentByte contentByte;
    protected PdfWriter writer;

    private PdfTemplate totalPageNoTemplate;
    private int lastPageNumber;

    // properties for header
    private bool done;
    // needs to be overriden in subclass order to use header feature
    protected string kundeHeader { get; set; }


    // font definitions
    protected BaseFont baseFont;
    protected Font fontFooter;
    protected Font fontGeneralText;
    protected Font fontLabelText;
    protected Font fontBoldLabelText;
    protected Font fontBoldText;
    protected Font fontSpace;
    protected Font fontLargeBoldText;

    protected int language;
    protected bool useLogo = false;
    protected bool usePageNumbers = false;
    protected bool usePrintDate = false;
    protected const string PRINT_FULLDATE_FORMAT = "dd.MM.yyyy HH:mm";
    protected const string PRINT_DATE_ONLY_FORMAT = "dd.MM.yyyy";

    protected Rectangle pagesize = PageSize.A4;
    protected float marginLeft = 80;
    protected float marginRight = 35;
    protected float marginTop = 40;
    protected float marginBottom = 40;

    private MemoryStream PDFStream { get; set; } = new MemoryStream();
    private DateTime printDate;

    public BaseReport(int language = Languages.DE, bool landscape = false)
    {
        this.language = language;
        if (landscape)
        {
            pagesize = pagesize.Rotate();
        }
    }


    public byte[] GenerateReport()
    {
        CultureInfo cultureBefore = Resources.Culture;
        try
        {
            Resources.Culture = SelectCultureForLangauge();
            PrepareReport();
            document = new Document(pagesize, marginLeft, marginRight, marginTop, marginBottom);
            BuildFonts();
            OpenDocument();
            PrepareDocument();
            GenerateContent();
            document.Close();
            return PDFStream.GetBuffer();
        } finally
        {
            Resources.Culture = cultureBefore;
        }
    }

    public void GenerateReport(string filename)
    {
        byte[] report = GenerateReport();
        using (FileStream f = new FileStream(filename, FileMode.Create))
        {
            f.Write(report, 0, report.Length);
        }
    }

    protected CultureInfo SelectCultureForLangauge()
    {
        string languageCode = GetLanguageCode();
        return CultureInfo.GetCultureInfo(languageCode);
    }

    protected string GetLanguageCode()
    {
        string languageCode = string.Empty;
        switch (language)
        {
            case Languages.FR: languageCode = "FR"; break;
            case Languages.IT: languageCode = "IT"; break;
            case Languages.EN: languageCode = "EN"; break;
            default: languageCode = "DE"; break;
        }

        return languageCode;
    }

    protected virtual void PrepareReport() { }

    protected virtual void PrepareDocument() { }

    protected abstract void GenerateContent();

    private void BuildFonts()
    {
        baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
        fontFooter = FontFactory.GetFont(FontFactory.HELVETICA, 11, Font.ITALIC, BaseColor.DARK_GRAY);
        fontGeneralText = FontFactory.GetFont(FontFactory.HELVETICA, 11, Font.NORMAL, BaseColor.BLACK);
        fontLabelText = FontFactory.GetFont(FontFactory.HELVETICA, 8.5f, Font.NORMAL, BaseColor.BLACK);
        fontBoldLabelText = FontFactory.GetFont(FontFactory.HELVETICA, 8.5f, Font.BOLD, BaseColor.BLACK);
        fontBoldText = FontFactory.GetFont(FontFactory.HELVETICA, 11, Font.BOLD, BaseColor.BLACK);
        fontSpace = FontFactory.GetFont(FontFactory.HELVETICA, 3.5f, Font.NORMAL, BaseColor.BLACK);
        fontLargeBoldText = FontFactory.GetFont(FontFactory.HELVETICA, 17, Font.BOLD, BaseColor.BLACK);
        GetFontIfAvailable();
    }

    private void GetFontIfAvailable()
    {
        string fileName = "IF_Rg";
        try
        {
            baseFont = LoadFontFromFile(fileName, true);
            fontFooter = new Font(baseFont, 11, Font.ITALIC, BaseColor.DARK_GRAY);
            fontGeneralText = new Font(baseFont, 11, Font.NORMAL, BaseColor.BLACK);
            fontLabelText = new Font(baseFont, 8.5f, Font.NORMAL, BaseColor.BLACK);
            fontBoldLabelText = new Font(baseFont, 8.5f, Font.BOLD, BaseColor.BLACK);
            fontBoldText = new Font(baseFont, 11, Font.BOLD, BaseColor.BLACK);
            fontSpace = new Font(baseFont, 3.5f, Font.NORMAL, BaseColor.BLACK);
            fontLargeBoldText = new Font(baseFont, 17, Font.BOLD, BaseColor.BLACK);
        } catch (FileNotFoundException)
        {
            LogWrapper.Warn("Font not found - using default.");
        }

    }

    protected BaseFont LoadFontFromFile(string fileName, bool embedded)
    {
        string fontPath = Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\" + fileName + ".ttf";
        if (File.Exists(fontPath))
        {
            return BaseFont.CreateFont(fontPath, BaseFont.WINANSI, embedded);
        }
        else
        {
            throw new FileNotFoundException($"Fontfile {fileName} was not found!");
        }
    }

    protected Image HeaderLogo()
    {
        Image logo = Image.GetInstance(Resources.logo, BaseColor.BLACK);
        // TODO msc pick logo from debitor
        logo.ScaleToFit(100f, 100f);
        return logo;
    }

    protected void OpenDocument()
    {
        writer = PdfWriter.GetInstance(document, PDFStream);
        writer.PageEvent = this;
        writer.SetFullCompression();
        document.Open();
        contentByte = writer.DirectContent;
    }

    protected void AddLabelAt(string label, float posX, float posY)
    {
        PdfContentByte cb = writer.DirectContent;
        ColumnText column = new ColumnText(cb);
        column.SetText(new Paragraph(label + NEWLINE, fontLabelText));
        column.SetSimpleColumn(posX, 20, posX + 200, posY);
        column.Go();
    }

    protected void AddLabelOnMargin(string label)
    {
        AddLabelAt(label, document.LeftMargin - 40, writer.GetVerticalPosition(false));
    }

    protected Phrase ParaLine(string Text, Font textfont)
    {
        return new Phrase(Text, textfont);
    }

    public override void OnOpenDocument(PdfWriter writer, Document document)
    {
        if (usePageNumbers)
        {
            totalPageNoTemplate = writer.DirectContentUnder.CreateTemplate(50, 50);
        }
        if (usePrintDate)
        {
            printDate = DateTime.Now;
        }
    }

    public override void OnStartPage(PdfWriter writer, Document document)
    {
        if (useLogo || (document.PageNumber > 1 && !string.IsNullOrEmpty(kundeHeader)))
        {
            PdfContentByte canvas = writer.DirectContentUnder;
            canvas.SaveState();
            if (document.PageNumber > 1 && !string.IsNullOrEmpty(kundeHeader))
            {
                //showtextaligned only shows a single line
                //therefor the header needs to be split and its parts need to be added seperately
                string[] headerParts = kundeHeader.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
                Phrase header = new Phrase(kundeHeader, fontLabelText);
                ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT,
                        ParaLine(headerParts[0], fontLabelText),
                        document.LeftMargin,
                        document.Top + 30, 0);
                ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT,
                        ParaLine(headerParts[1], fontLabelText),
                        document.LeftMargin,
                        document.Top + 20, 0);
            }
            if (useLogo)
            {                     
                Image logo = HeaderLogo();
                logo.SetAbsolutePosition(marginLeft - 17.5f, document.Top + document.TopMargin - 50);
                document.Add(logo);
            }
            canvas.RestoreState();
        }
    }

    public override void OnEndPage(PdfWriter writer, Document document)
    {
        if (usePageNumbers || usePrintDate)
        {
            PdfContentByte canvas = writer.DirectContentUnder;
            canvas.SaveState();
            if (usePageNumbers)
            {
                // adds current page number to the footer section of the document
                int pageN = writer.PageNumber;
                string text = Resources.LabelSeite + SPACE + pageN + "/";
                float len = fontLabelText.BaseFont.GetWidthPoint(text, fontLabelText.Size);
                ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT,
                        ParaLine(text, fontLabelText),
                        document.LeftMargin,
                        document.Bottom - 10, 0);
                // adds template to fill in total page number (see OnCloseDocument method)
                canvas.AddTemplate(totalPageNoTemplate, document.LeftMargin + len, document.Bottom - 10);
                lastPageNumber = pageN;
            }
            if (usePrintDate)
            {
                // adds the printdate to the footer secdtion of the document
                string dateFormatted = printDate.ToString(PRINT_FULLDATE_FORMAT);
                ColumnText.ShowTextAligned(canvas, Element.ALIGN_RIGHT,
                        ParaLine(dateFormatted, fontLabelText),
                        document.Right,
                        document.Bottom - 10, 0);
            }
            canvas.RestoreState();
        }
    }

    public override void OnCloseDocument(PdfWriter writer, Document document)
    {
        if (usePageNumbers)
        {
            // fills in the total page number to the prepared template in the footer section of the document
            string text = lastPageNumber + "";
            float widthPoint = fontLabelText.BaseFont.GetWidthPoint(text, fontLabelText.Size);
            totalPageNoTemplate.Width = widthPoint;
            ColumnText.ShowTextAligned(totalPageNoTemplate, Element.ALIGN_LEFT, ParaLine(text, fontLabelText), 0, 0, 0);
        }
    }


我必须将PDFStream.GetBuffer()与PDFStream.ToArray()切换;问题已解决。

大多数PDF查看器都能容忍较小的PDF语法问题。Adobe也很宽容,但希望解决这些问题。这就是为什么会出现一个对话框,询问您是否要保存文档。Adobe希望修复此问题,以便下次打开文档时不会发生此问题。如果您使用的是iText 5.2.x,则应升级,因为该版本存在已知问题。我们不知道其他版本存在问题,尽管如果代码错误,使用iText创建错误的PDF总是可能的。如果看不到您的代码或PDF,没有人可以回答您的问题。请注意,使用iText填写奇怪的表单时也会出现此问题。您可以通过修复表单或以不同的方式填写表单来避免问题(如果这适用于您,请向我们展示您的代码)。至于“收缩”:我打赌你创建PDF的方式与PDF 1.5之前创建PDF的方式相同。从PDF 1.5开始,可以压缩交叉引用表和特定对象(在iText中,我们称之为完全压缩)。当Adobe Reader保存PDF的固定版本时,它可能会压缩
xref
表和所选对象。感谢您的快速响应!我使用的是iTextSharp 5.5.10.0,所以应该可以。因此,如果我对我的报告实施
完全压缩
,AdobeReader应该可以吗?如果您需要帮助,请共享您的PDF。我们可以检查它是否是一个表单(用于解决已知问题)。如果它不是一个表单,我们可以使用飞行前验证它,以查看Adobe Reader抱怨的语法错误。您还可以共享您的代码,以便我们查看您是否执行了与ISO 32000冲突的低级操作。一个显而易见的错误是,您正在
OnStartPage()
方法中添加内容。这是禁止的(如文件所述)。此外,在该方法中使用的是
document.Add()
。禁止在页面事件实现中使用
文档
对象,因为
文档
对象不是您认为的
文档
对象。它实际上是一个内部
PdfDocument
实例,只应用于只读目的。旧版本的iText中的所有这些设计缺陷都在iText 7.Ah中修复。因此,这实际上是一个重复的问题,应该标记为这样。。。