如何用iText7 C#将附件设为PDF作品集封面(无需新增页面)
问题:将附件文件设为PDF作品集封面,无需新增空白页
我希望将一个附件文件设置为我的PDF作品集的封面。目前我的代码中必须添加
doc.Add(new Paragraph("Portable collection"));,否则会出现“文档无页面”的错误。请问有没有办法用文件作为封面,而不需要新增页面?感谢解答。
用户提供的代码:
public Stream ExportPortfolio() { DateTime dateTime = DateTime.UtcNow.Date; CreatePortfolio port = new CreatePortfolio(); //dummy files in local Dictionary<string, FileStream> dict = new Dictionary<string, FileStream>() { { "pdf.pdf", File.OpenRead(@"C:\training\pdf.pdf") }, { "text.txt", File.OpenRead(@"C:\training\text.txt") }, }; WebOperationContext.Current.OutgoingResponse.ContentType = "application/octet-stream"; WebOperationContext.Current.OutgoingResponse.Headers.Add("content-disposition", "inline; filename=" + $"{dateTime.ToString("dd/MM/yyyy")}_portfolio.pdf"); return ManipulatePdf(dict); } public Stream ManipulatePdf(Dictionary<string, FileStream> Portfolios) { MemoryStream stream = new MemoryStream(); PdfDocument pdfDoc = new PdfDocument(new PdfWriter(stream)); Document doc = new Document(pdfDoc); doc.Add(new Paragraph("Portable collection")); PdfCollection collection = new PdfCollection(); collection.SetView(PdfCollection.TILE); pdfDoc.GetCatalog().SetCollection(collection); foreach (var item in Portfolios) { AddFileAttachment(pdfDoc, item.Value, item.Key); } doc.Close(); byte[] file = stream.ToArray(); MemoryStream output = new MemoryStream(); output.Write(file, 0, file.Length); output.Position = 0; return output; } private void AddFileAttachment(PdfDocument document, FileStream fileStream, string fileName) { string embeddedFileName = fileName; string embeddedFileDescription = fileName; string fileAttachmentKey = fileName; PdfFileSpec fileSpec = PdfFileSpec.CreateEmbeddedFileSpec(document, fileStream, embeddedFileDescription, embeddedFileName, null, null); document.AddFileAttachment(fileAttachmentKey, fileSpec); }
解决方案
核心原因是PDF规范要求文档至少包含一页内容,你可以直接将目标封面文件的页面导入新文档,替代原来的空白段落。具体实现如下:
- 从附件字典中取出要作为封面的PDF文件流
- 使用
PdfReader读取该流,将其页面复制到新创建的PdfDocument中 - 删除原有的
doc.Add(new Paragraph("Portable collection"));代码行
修改后的ManipulatePdf方法代码:
public Stream ManipulatePdf(Dictionary<string, FileStream> Portfolios) { MemoryStream stream = new MemoryStream(); PdfDocument pdfDoc = new PdfDocument(new PdfWriter(stream)); Document doc = new Document(pdfDoc); // 导入封面PDF的第一页作为文档首页 if (Portfolios.ContainsKey("pdf.pdf")) { // 重置流位置,避免读取时指针在末尾导致无内容 Portfolios["pdf.pdf"].Position = 0; using (PdfReader coverReader = new PdfReader(Portfolios["pdf.pdf"])) { using (PdfDocument coverDoc = new PdfDocument(coverReader)) { // 复制封面PDF的第一页到新文档,如需多页可调整参数为1, coverDoc.GetNumberOfPages(), pdfDoc coverDoc.CopyPagesTo(1, 1, pdfDoc); } } } PdfCollection collection = new PdfCollection(); collection.SetView(PdfCollection.TILE); pdfDoc.GetCatalog().SetCollection(collection); foreach (var item in Portfolios) { // 重置流位置,确保附件能正确嵌入 item.Value.Position = 0; AddFileAttachment(pdfDoc, item.Value, item.Key); } doc.Close(); byte[] file = stream.ToArray(); MemoryStream output = new MemoryStream(); output.Write(file, 0, file.Length); output.Position = 0; return output; }
注意事项
- 操作文件流时必须重置位置(
Position = 0),因为读取流后指针会停在末尾,后续复用会读不到内容 - 如果封面PDF有多页,可调整
CopyPagesTo的参数导入全部页面 - 确保封面文件是合法的PDF格式,否则会导致读取失败
内容的提问来源于stack exchange,提问作者ItecStudent
相关产品推荐
相关产品推荐

