使用Spire.PDF转换服务器PDF为Tiff时触发GDI+通用错误
解决Spire.PDF转Tiff时GDI+通用错误的方案
这个A generic error occurred in GDI+错误在处理图像文件时真的很常见,结合你的代码,我整理了几个大概率的原因和对应的修复方法:
1. 先排查文件路径与权限问题
你当前写的"res.tiff"是相对路径,ASP.NET程序运行时的工作目录大概率不是你预期的位置,而且IIS应用池账号可能没有该目录的写入权限,这是触发GDI+错误的高频原因。
修复步骤:
- 改用绝对路径,比如指定到网站的可写入目录(推荐用App_Data,默认有写入权限):
string saveDir = Server.MapPath("~/App_Data/"); string outFile = Path.Combine(saveDir, "res.tiff"); - 提前确保目标目录存在,避免因目录不存在导致写入失败:
if (!Directory.Exists(saveDir)) { Directory.CreateDirectory(saveDir); } - 如果还是报错,检查目标目录的权限,给IIS应用池账号(比如
IIS AppPool\你的应用池名称)添加写入权限。
2. 释放Image资源,避免GDI+资源锁定
GDI+对图像资源的管理非常严格,如果Image对象没有正确释放,会导致文件被锁定,根本无法写入。你的代码里有几个明显的资源泄漏点:
修复后的JoinTiffImages方法:
public static void JoinTiffImages(Image[] images, string outFile, EncoderValue compressEncoder) { Encoder enc = Encoder.SaveFlag; EncoderParameters ep = new EncoderParameters(2); ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.MultiFrame); ep.Param[1] = new EncoderParameter(Encoder.Compression, (long)compressEncoder); Image pages = null; try { int frame = 0; ImageCodecInfo info = GetEncoderInfo("image/tiff"); foreach (Image img in images) { using (img) // 自动释放每个单页图像的资源 { if (frame == 0) { pages = new Bitmap(img); // 复制第一个图像,避免原对象被释放后失效 pages.Save(outFile, info, ep); } else { ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.FrameDimensionPage); pages.SaveAdd(img, ep); } if (frame == images.Length - 1) { ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.Flush); pages.SaveAdd(ep); } frame++; } } } finally { pages?.Dispose(); // 释放最终拼接的多页图像 ep.Dispose(); // 释放编码器参数资源 } }
另外在OpenFilee方法中也要释放资源:
public ActionResult OpenFilee(string fileID) { string pdfPath = Path.Combine(Server.MapPath("~/SafetyUploadedFiles/"), fileID); using (PdfDocument doc = new PdfDocument()) { doc.LoadFromFile(pdfPath); Image[] pdfImages = SaveAsImage(doc); try { string saveDir = Server.MapPath("~/App_Data/"); if (!Directory.Exists(saveDir)) { Directory.CreateDirectory(saveDir); } string outFile = Path.Combine(saveDir, "res.tiff"); JoinTiffImages(pdfImages, outFile, EncoderValue.CompressionLZW); // 注意:ASP.NET服务器端不能用Process.Start,要返回文件给客户端 return File(outFile, "image/tiff", "result.tiff"); } finally { foreach (Image img in pdfImages) { img.Dispose(); } } } }
3. 修正MultiFrame保存的逻辑漏洞
原代码中直接pages = img;赋值第一个图像,后续如果img被释放,pages会变成无效对象,用new Bitmap(img)复制一份可以避免这个问题,上面的代码已经包含了这个修改。
额外提醒:ASP.NET中别用Process.Start
你原来写的System.Diagnostics.Process.Start("res.tiff");是在服务器端执行的,服务器没有桌面环境,不会弹出图像查看器,对客户端完全没用。如果要让用户看到生成的Tiff,应该用return File()把文件返回给客户端,就像上面代码里写的那样。
内容的提问来源于stack exchange,提问作者Reply not
相关产品推荐
相关产品推荐

