iTextSharp 5 生成的 PDF 文档 AdobeReader 兼容性
iTextSharp 5 generated PDF-Document AdobeReader-compatibility
我正在使用 iTextSharp 5 生成一些报告。
打开生成的 .PDF 文件,对于大多数 PDF 阅读器来说,一切看起来都很好。
但是,当我使用 AdobeReader(DC) 打开 PDF 时,它会询问我是否要在关闭时保存更改。虽然我什么都没改。
点击 'Cancel' 肯定会使消息 window 消失,但点击保存会导致文件实际缩小。
现在那里发生了什么?为什么?我怎样才能禁用它?
该应用程序的用户很可能也会使用 AdobeReader。
我不希望他们在打开报告时看到保存对话框。
这是我的 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() 切换;问题已解决。
我正在使用 iTextSharp 5 生成一些报告。
打开生成的 .PDF 文件,对于大多数 PDF 阅读器来说,一切看起来都很好。
但是,当我使用 AdobeReader(DC) 打开 PDF 时,它会询问我是否要在关闭时保存更改。虽然我什么都没改。
点击 'Cancel' 肯定会使消息 window 消失,但点击保存会导致文件实际缩小。
现在那里发生了什么?为什么?我怎样才能禁用它?
该应用程序的用户很可能也会使用 AdobeReader。
我不希望他们在打开报告时看到保存对话框。
这是我的 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() 切换;问题已解决。