iTextSharp 从字节数组列表创建 pdf
Posted
技术标签:
【中文标题】iTextSharp 从字节数组列表创建 pdf【英文标题】:iTextSharp creation of a pdf from a list of byte arrays 【发布时间】:2011-04-27 02:00:08 【问题描述】:我有一个 byte[] 列表,我想将其连接成一个 byte[],这将是最终的 PDf。
在“page = copy.GetImportedPage(new PdfReader(p), i);”上,我得到一个“对象引用未设置为实例错误。
我不知道发生了什么,我已经检查了每个对象并且没有空值。
关于这个的任何想法,或另一段可以成功的代码?!
我有这个方法:
编辑
public static byte[] concatAndAddContent(List<byte[]> pdf)
byte [] todos;
using(MemoryStream ms = new MemoryStream())
Document doc = new Document();
doc.Open();
PdfCopy copy = new PdfCopy(doc, ms);
PdfCopyFields copy2 = new PdfCopyFields(ms);
PdfReader reader;
foreach (byte[] p in pdf)
reader = new PdfReader(p);
int pages = reader.NumberOfPages;
// loop over document pages
for (int i = 1; i < pages; i++)
PdfImportedPage page = copy.GetImportedPage(reader, i);
PdfCopy.PageStamp stamp = copy.CreatePageStamp(page);
PdfContentByte cb = stamp.GetUnderContent();
cb.SaveState();
stamp.AlterContents();
copy.AddPage(page);
doc.Close();
todos = ms.GetBuffer();
ms.Flush();
ms.Dispose();
return todos;
堆栈跟踪:
[NullReferenceException: Object reference not set to an instance of an object.]
iTextSharp.text.pdf.PdfImportedPage..ctor(PdfReaderInstance readerInstance, PdfWriter writer, Int32 pageNumber) +45
iTextSharp.text.pdf.PdfReaderInstance.GetImportedPage(Int32 pageNumber) +175
iTextSharp.text.pdf.PdfCopy.GetImportedPage(PdfReader reader, Int32 pageNumber) +256
SAM.Web.Classes.UtileriasReportes.concatAndAddContent(List`1 pdf) in \Classes\UtileriasReportes.cs:199
SAM.Web.Classes.UtileriasReportes.ObtenReporteOdt(Int32 ordenTrabajoID, Boolean caratula, Boolean juntas, Boolean cortes, Boolean materiales, Boolean resumenMateriales)
in D:\MIMOSS\Desarrollo\SAM 2.0\Desarrollo\WebSolution\SAM.Web\Classes\UtileriasReportes.cs:168
SAM.Web.Produccion.PopupImpresionOdt.btnImprimir_Click(Object sender, EventArgs e) in \PopupImpresionOdt.aspx.cs:44
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +118
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +112
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5563
感谢您的宝贵时间!
【问题讨论】:
我已经添加了堆栈跟踪。感谢您的宝贵时间! 只是要指出的另一件小事。因为 GetImportedPage 不是基于 0 的,所以您必须从 1 开始您的 i val。现在只需确保您的页面值 (NumberOfPages) 允许您获取所有数据。现在您似乎缺少任何 PDF 文档的最后一页。 感谢您的建议,我马上去检查,谢谢大家! 【参考方案1】:此解决方案适用于 iText 7.1.8:
它基于以前的答案和新的API Examples
public static byte[] MergePDFs(List<byte[]> lPdfByteContent)
using (MemoryStream oMemoryStream = new MemoryStream())
using (PdfWriter oWriter = new PdfWriter(oMemoryStream))
oWriter.SetSmartMode(true);
using (PdfDocument oMergedPdf = new PdfDocument(oWriter))
PdfMerger oMerger = new PdfMerger(oMergedPdf, false, false);
for (int i = 0; i < lPdfByteContent.Count; i++)
PdfDocument oPdfAux = new PdfDocument(new PdfReader(new MemoryStream(lPdfByteContent[i])));
oMerger.SetCloseSourceDocuments(true).Merge(oPdfAux, 1, oPdfAux.GetNumberOfPages());
return oMemoryStream.ToArray();
【讨论】:
【参考方案2】:这行得通:
使用iTextSharp-LGPL4.1.6:
public static byte[] ConcatenatePdfs(IEnumerable<byte[]> documents)
using (var ms = new MemoryStream())
var outputDocument = new Document();
var writer = new PdfCopy(outputDocument, ms);
outputDocument.Open();
foreach (var doc in documents)
var reader = new PdfReader(doc);
for (var i = 1; i <= reader.NumberOfPages; i++)
writer.AddPage(writer.GetImportedPage(reader, i));
writer.FreeReader(reader);
reader.Close();
writer.Close();
outputDocument.Close();
var allPagesContent = ms.GetBuffer();
ms.Flush();
return allPagesContent;
【讨论】:
【参考方案3】:我最初使用上面的答案并且 PDF 非常大。我认为返回并提供这个链接会很有帮助,它完全解决了这个问题以及我的 LARGE PDF 问题。
https://***.com/a/6752769
【讨论】:
【参考方案4】:我已经想通了,这样每个人都可以有解决方案: 在这里:
public static byte[] concatAndAddContent(List<byte[]> pdf)
byte [] all;
using(MemoryStream ms = new MemoryStream())
Document doc = new Document();
PdfWriter writer = PdfWriter.GetInstance(doc, ms);
doc.SetPageSize(PageSize.LETTER);
doc.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
PdfReader reader;
foreach (byte[] p in pdf)
reader = new PdfReader(p);
int pages = reader.NumberOfPages;
// loop over document pages
for (int i = 1; i <= pages; i++)
doc.SetPageSize(PageSize.LETTER);
doc.NewPage();
page = writer.GetImportedPage(reader, i);
cb.AddTemplate(page, 0, 0);
doc.Close();
all = ms.GetBuffer();
ms.Flush();
ms.Dispose();
return all;
希望有帮助!
【讨论】:
你是个传奇!感谢您回来分享这个金块。 遇到错误PDF header signature not found.
可以帮忙【参考方案5】:
查看 itextsharp 代码,它可能并不总是适用于同一内容的多个阅读器。
建议你试试
page = copy.GetImportedPage(reader, i);
而不是为您尝试阅读的每个页面创建一个新的阅读器。
更新:我不知道是否有帮助,但是
我复制并粘贴了您的代码,但我得到了 NullReferenceException 但仅在这一行
stamp.AlterContents();
这很奇怪,因为那是在你得到它之后。+
当在列表中传递不良内容时,我能够产生 Missing PDF header、Trailer Not found 等,所以我认为 p 的内容没有区别
我用的是5.0.4版本,源码版本是VS 2008内置的,客户端是vs 2010的,也许这些是区别的原因。
【讨论】:
感谢您的回复,但这并没有帮助,我编辑了代码,所以这就是我现在所拥有的: PdfReader 阅读器; foreach (byte[] p in pdf) reader = new PdfReader(p); int pages = reader.NumberOfPages; // 遍历文档页面 for (int i = 0; i 我的错,我实际上修改了将 byte[] 名称从 todos 更改为 all 的代码,并且错过了它,但这不是问题。我将编辑代码并保持原样。感谢您的帮助。 我更新了我的答案以删除有关编译错误的部分,但老实说,我认为这不会有帮助。就像我说的那样,我尝试传递愚蠢的内容来尝试重现您的问题,但 iTextSharp 在面对不良内容时非常强大 这可能是问题所在。我在vs2010中使用的是4.1.2版本,我会尝试查找最新版本并试一试。感谢您的帮助,我会更新结果。【参考方案6】:不确定这是否会为您解决问题,但请尝试从第 1 页开始初始化 GetImportedPage,不是零,而是在您的 for 循环中使用 int i = 1
。像这样:
// loop over document pages
//was (int i = 0; i < pages; i++)
for (int i = 1; i < pages; i++)
page = copy.GetImportedPage(new PdfReader(p), i);
stamp = copy.CreatePageStamp(page);
PdfContentByte cb = stamp.GetUnderContent();
cb.SaveState();
stamp.AlterContents();
copy.AddPage(page);
【讨论】:
实际上是正确的,使用 GetImportedPage(reader, 0) 它会返回一个错误,但是从 1 开始页面总是给我空引用异常。我在这里迷路了,无法理解为什么。谢谢,非常感谢您的帮助!以上是关于iTextSharp 从字节数组列表创建 pdf的主要内容,如果未能解决你的问题,请参考以下文章