iTextSharp 5 生成的 PDF 文档 Adob​​eReader 兼容性

iTextSharp 5 generated PDF-Document AdobeReader-compatibility

我正在使用 iTextSharp 5 生成一些报告。

打开生成的 .PDF 文件,对于大多数 PDF 阅读器来说,一切看起来都很好。

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

点击 'Cancel' 肯定会使消息 window 消失,但点击保存会导致文件实际缩小。

现在那里发生了什么?为什么?我怎样才能禁用它?

该应用程序的用户很可能也会使用 Adob​​eReader。

我不希望他们在打开报告时看到保存对话框。

这是我的 BaseReport class

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);
        }
    }

iTextSharp-generated PDFs now cause Save dialog in Adobe Reader X

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