c# - itextsharp 5 writer.DirectContent 创建的文件比 PDFStamper 小 50%
问题描述
我真的很想使用使用 PDFStamper 的新方法,而不是使用 (PdfWriter.GetInstance... writer.DirectContent) 的旧方法,但是使用旧方法创建的 PDF 文件的大小是使用新方法的 1/2 . 这两种方法之间有什么我缺少的吗?
//Old way using PdfWriter.GetInstance... writer.DirectContent
public static void AddHeaderTextLayer()
{
string HdrLeft = string.Empty;
string HdrRight = string.Empty;
string PageHdrName = "XHdr";
string NoOfPagesPadded = string.Empty;
string PageNoPadded = string.Empty;
int xLeft = 30;
int xRight = 100;
int xTop = 15;
string filename = "4_20140909.pdf";
PdfReader reader = new PdfReader(@"C:\!stuff\Junk\ChemWatchPDF\" + filename); // input file
using (var fileStream = new FileStream(@"C:\!stuff\Junk\ChemWatchPDF\" + filename.Replace(".pdf", "") + "_withHdrLTp.pdf", FileMode.Create, FileAccess.Write))
{
var document = new Document(reader.GetPageSizeWithRotation(1));
var writer = PdfWriter.GetInstance(document, fileStream);
document.Open();
for (var i = 1; i <= reader.NumberOfPages; i++)
{
Rectangle pageRect = reader.GetPageSize(i);
document.NewPage();
var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
var importedPage = writer.GetImportedPage(reader, i);
var contentByte = writer.DirectContent;
contentByte.AddTemplate(importedPage, 0, 0);
string SDSNo = "12345678";
HdrLeft = $"Company MSDS# {SDSNo}";
NoOfPagesPadded = (reader.NumberOfPages.ToString());
PageNoPadded = i.ToString();
HdrRight = $" Page {PageNoPadded} of {NoOfPagesPadded}";
contentByte.BeginLayer(new PdfLayer(PageHdrName + i.ToString(), writer));
contentByte.BeginText();
contentByte.SetFontAndSize(baseFont, 10);
contentByte.SetColorFill(LabColor.RED);
contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, HdrLeft, pageRect.Left + xLeft, pageRect.Top - xTop, 0);
contentByte.EndText();
contentByte.BeginText();
contentByte.SetFontAndSize(baseFont, 10);
contentByte.SetColorFill(LabColor.RED);
contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, HdrRight, pageRect.Right - xRight, pageRect.Top - xTop, 0);
contentByte.EndText();
contentByte.EndLayer();
}
document.Close();
writer.Close();
}
}
// New way using PDFStamper
public void Add()
{
BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, Encoding.ASCII.EncodingName, false);
string outPutFile = string.Empty;
var SingleLine = string.Empty;
string HdrLeft = string.Empty;
string HdrRight = string.Empty;
string PageHdrName = "xHdr";
string NoOfPagesPadded = string.Empty;
string PageNoPadded = string.Empty;
int xLeft = 30;
int xRight = 100;
int xTop = 15;
string filename = "4_20140909.pdf";
outPutFile = @"C:\!stuff\Junk\ChemWatchPDF\" + filename.Replace(".pdf", "") + "_withHdrLTStamp.pdf";
using (var newPDF = new FileStream(outPutFile, FileMode.Create, FileAccess.ReadWrite))
{
PdfReader reader = new PdfReader(@"C:\!stuff\Junk\ChemWatchPDF\" + filename); // input file
PdfStamper pdfStamper = new PdfStamper(reader, newPDF);
PdfLayer wmLayer = new PdfLayer(PageHdrName, pdfStamper.Writer);
for (int page = 1; page <= reader.NumberOfPages; page++)
{
PdfContentByte pdfContent = pdfStamper.GetOverContent(page);
Rectangle pageRect = reader.GetPageSize(page);
string SDSNo = "12345678";
HdrLeft = $"Company MSDS# {SDSNo}";
NoOfPagesPadded = (reader.NumberOfPages.ToString());
PageNoPadded = page.ToString();
HdrRight = $"Page {PageNoPadded} of {NoOfPagesPadded}";
pdfContent.BeginLayer(wmLayer);
pdfContent.BeginText();
pdfContent.SetFontAndSize(baseFont, 10);
pdfContent.SetColorFill(LabColor.RED);
pdfContent.ShowTextAligned(PdfContentByte.ALIGN_LEFT, HdrLeft, pageRect.Left + xLeft, pageRect.Top - xTop, 0);
pdfContent.EndText();
pdfContent.BeginText();
pdfContent.SetFontAndSize(baseFont, 10);
pdfContent.SetColorFill(LabColor.RED);
pdfContent.ShowTextAligned(PdfContentByte.ALIGN_LEFT, HdrRight, pageRect.Right - xRight, pageRect.Top - xTop, 0);
pdfContent.EndText();
pdfContent.EndLayer();
}
pdfStamper.Close();
}
}
}
}
解决方案
您的盖章副本(“较新方法”的输出)包含一个结构树,我假设它来自原始文档。它在“旧方法”的输出中丢失了。
结构树描述了文档的逻辑结构。它增加了文档的可访问性,并且它的存在成为越来越多的国家和环境中的法律要求。因此,一般来说丢弃结构树是一个坏主意。
结构树本身由非常多的小型间接对象组成,如果您的 PDF 有 1000 多个间接对象,总大小约为 90KB。此外,每个间接对象都需要一个 20 字节的交叉引用条目,在您的情况下总计将近 20KB。这几乎解释了两个输出之间 111KB 的大小差异。
如果使用对象流和交叉引用流,通常可以很好地压缩结构树。因此,我建议您在 iText 中激活完全压缩,使其使用对象流和交叉引用流:
PdfStamper pdfStamper = new PdfStamper(reader, newPDF);
pdfStamper.SetFullCompression();
pdfStamper.Writer.CompressionLevel = 9;
通过PdfReader/PdfStamper
使用这些设置简单地处理您的大型 PDF,无需任何其他操作,我将您的文件大小从 234KB 减少到 133KB。
顺便说一句,您将使用PdfWriter
页面导入的方法称为“旧方法”,将方法PdfStamper
称为“新方法”。实际上PdfStamper
,至少自 2003 年以来,该类就存在于 iText 中!所以它并不是真正的旧与新......
推荐阅读
- c# - 连接到本地主机上的端口时出现“SocketException:不知道这样的主机”
- php - tmp 文件未上传 PHP
- highcharts - 折线图的升压模式下不显示数据标签
- xamarin - 我们可以使用命令行工具创建一个新的 Xamarin 表单项目吗?
- ios - 在后台获取时调用完整函数时,我什么时候需要使用“.noData”?
- oracle - ANSI JOINS 和 UNIONS 不允许我在 RTMV 的查询计算上使用 ENABLE
- excel - 如何编写使用写入它的单元格作为参考的 UDF
- scala - 如何从 build.sbt 指定特定测试
- date - 日期范围 Visual Basic 脚本未按预期工作?
- javascript - webpack 如何读取要导入的内容?