如何在C#/.NET Core中通过iText7合并PDF与图片文件
实现PDF与图片混合文件的合并(基于List)
要搞定PDF和图片混合文件的合并,核心逻辑是先把所有图片转换成单页PDF,再将所有PDF(包括原有的PDF和转好的图片PDF)合并成一个最终文件。下面是具体的实现步骤和代码示例,针对ASP.NET Core中List<IFormFile>的接收场景:
1. 依赖准备
首先需要安装两个NuGet包:
iTextSharp.LGPLv2.Core:用于PDF的创建和合并操作(LGPL协议,可商用)SixLabors.ImageSharp:用于图片的读取和处理
使用.NET CLI安装的命令:
dotnet add package iTextSharp.LGPLv2.Core dotnet add package SixLabors.ImageSharp
2. 核心方法实现
2.1 图片转单页PDF
这个方法负责将上传的图片文件转换成只包含单页的PDF流:
private MemoryStream ConvertImageToPdf(IFormFile imageFile) { var pdfStream = new MemoryStream(); using (var image = SixLabors.ImageSharp.Image.Load(imageFile.OpenReadStream())) { // 根据图片尺寸创建PDF文档 var pdfDoc = new iTextSharp.text.Document(new iTextSharp.text.Rectangle(image.Width, image.Height)); PdfWriter.GetInstance(pdfDoc, pdfStream); pdfDoc.Open(); // 将图片添加到PDF页面 var pdfImage = iTextSharp.text.Image.GetInstance(imageFile.OpenReadStream()); pdfImage.ScaleToFit(pdfDoc.PageSize.Width, pdfDoc.PageSize.Height); pdfDoc.Add(pdfImage); pdfDoc.Close(); } pdfStream.Position = 0; return pdfStream; }
2.2 合并多个PDF流
这个方法将所有PDF流(原PDF和图片转的PDF)合并成一个完整的PDF:
private MemoryStream MergePdfs(List<MemoryStream> pdfStreams) { var mergedStream = new MemoryStream(); var mergedDoc = new iTextSharp.text.Document(); var pdfCopy = new PdfCopy(mergedDoc, mergedStream); mergedDoc.Open(); foreach (var stream in pdfStreams) { stream.Position = 0; using (var pdfReader = new PdfReader(stream)) { // 逐页添加到合并文档中 for (int pageNum = 1; pageNum <= pdfReader.NumberOfPages; pageNum++) { pdfCopy.AddPage(pdfCopy.GetImportedPage(pdfReader, pageNum)); } } } mergedDoc.Close(); mergedStream.Position = 0; return mergedStream; }
3. 主处理流程
在接口方法中处理上传的List<IFormFile>,区分PDF和图片,转换后合并:
public async Task<IActionResult> MergeUploadedFiles(List<IFormFile> files) { var pdfStreams = new List<MemoryStream>(); foreach (var file in files) { if (string.IsNullOrWhiteSpace(file.FileName)) continue; // 处理PDF文件 if (file.ContentType.Equals("application/pdf", StringComparison.OrdinalIgnoreCase) || file.FileName.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase)) { var pdfMs = new MemoryStream(); await file.CopyToAsync(pdfMs); pdfMs.Position = 0; pdfStreams.Add(pdfMs); } // 处理图片文件(png/jpg/jpeg等) else if (file.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase) || new[] { ".png", ".jpg", ".jpeg" }.Any(ext => file.FileName.EndsWith(ext, StringComparison.OrdinalIgnoreCase))) { var imagePdfMs = ConvertImageToPdf(file); pdfStreams.Add(imagePdfMs); } // 其他格式可选择跳过或抛出错误 } if (!pdfStreams.Any()) { return BadRequest("未找到可合并的PDF或图片文件"); } var mergedPdf = MergePdfs(pdfStreams); // 返回合并后的PDF文件,浏览器会自动下载或预览 return File(mergedPdf, "application/pdf", $"merged_{DateTime.Now:yyyyMMddHHmmss}.pdf"); }
4. 关键注意事项
- 文件类型校验:不要只依赖
ContentType,结合文件扩展名一起判断,避免恶意文件伪装 - 内存管理:所有流操作尽量用
using语句包裹,确保资源正确释放,防止内存泄漏 - 异常处理:建议在实际代码中添加
try-catch块,处理文件损坏、读取失败等异常情况 - 图片适配:如果图片尺寸过大,可在转换时调整为标准PDF页面尺寸(如A4),避免生成的PDF页面尺寸异常
内容的提问来源于stack exchange,提问作者Akter
相关产品推荐
相关产品推荐

