如何将FileContentResult数据写入PDF并添加至压缩包?
解决方案
核心思路
不需要将FileContentResult先写入物理PDF文件,直接提取其内部的PDF字节数组,通过内存流构建压缩包,最终返回压缩包供下载,全程避免磁盘IO操作,效率更高。
代码修改与实现
- 修正原代码中的资源泄漏问题(用
using包裹流),并调整FileContentResult的文件名参数:
[HttpPost] public ActionResult Create(Job newJob) { string path = MyServer.MapPath(@"\Files\"); DirectoryInfo d = new DirectoryInfo(path); List<FileContentResult> fileContentResults = new List<FileContentResult>(); foreach (var file in d.GetFiles("*.pdf")) { if (System.IO.File.Exists(file.FullName)) { // 使用using自动释放流资源 using (var sourceFileStream = System.IO.File.OpenRead(file.FullName)) using (var outputStream = new MemoryStream()) { var pdf = new PdfDocument(new PdfReader(sourceFileStream), new PdfWriter(outputStream)); PdfAcroForm form = PdfAcroForm.GetAcroForm(pdf, false); IDictionary<String, PdfFormField> fields = form.GetAllFormFields(); if (fields != null) { // 填充表单字段示例: // fields["JobTitle"].SetValue(newJob.Title); // fields["JobId"].SetValue(newJob.Id.ToString()); } pdf.Close(); byte[] bytes = outputStream.ToArray(); // 用file.Name作为下载文件名,避免全路径 fileContentResults.Add(File(bytes, System.Net.Mime.MediaTypeNames.Application.Pdf, file.Name)); } } } // 构建压缩包并返回 using (var zipStream = new MemoryStream()) { using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) { foreach (var fileResult in fileContentResults) { // 在压缩包中创建对应条目 var zipEntry = archive.CreateEntry(fileResult.FileDownloadName); // 将PDF字节数组写入压缩条目 using (var entryStream = zipEntry.Open()) { entryStream.Write(fileResult.FileContents, 0, fileResult.FileContents.Length); } } } // 重置压缩流指针到起始位置 zipStream.Position = 0; // 返回压缩包,指定MIME类型和下载文件名 return File(zipStream, "application/zip", "filled_job_forms.zip"); } }
- 必要的命名空间引用:
using System.IO; using System.IO.Compression; using iText.Kernel.Pdf; using iText.Forms;
关键说明
FileContentResult.FileContents就是填充完成的PDF字节数组,直接提取使用即可,无需额外写入磁盘。- 使用
ZipArchive在内存中构建压缩包,避免了磁盘文件的创建与删除操作,提升性能。 - 最终返回
File(zipStream, ...)会直接将压缩包输出给客户端,用户可直接下载。
内容的提问来源于stack exchange,提问作者Xs_
相关产品推荐
相关产品推荐

