今天在压缩商城的图片是,领略到释放资源的重要性。尤其是在操作文件时,如果不及时释放对文件的访问权,就会导致错误。
在压缩完图片,尝试覆盖原图片时,系统提示:GDI+ 中发生一般性错误。
Google了一下,得到3中可能性:
在开发.NET应用中,使用 System.Drawing.Image.Save 方法而导致“GDI+ 中发生一般性错误”的发生,通常有以下三种原因:
1. 相应的帐户没有写权限。
解决方法:赋予 NETWORK SERVICE 帐户以写权限。
2. 指定的物理路径不存在。
解决方法:
在调用 Save 方法之前,先判断目录是否存在,若不存在,则创建。
if (!Directory.Exists(dirpath))
Directory.CreateDirectory(dirpath);
3. 保存的文件已存在并因某种原因被锁定。
解决方法:
重启IIS,解除锁定。并在代码中使用 using 语句,确保释放 Image 对象所使用的所有资源。
根据猜想,估计是第三种。那么就是资源没有释放啦。在swfupload这个项目的samples中有一个.net生成缩略图的例子,而我,正是照着这个例子来做的。仔细看了它的代码,发现它还有一个释放资源的try...catch...finally语句。
下面是我最后改好的例子:
private string FixPic2(string pic)
{
if (!System.IO.File.Exists(pic))
return null;
System.Drawing.Image image = System.Drawing.Image.FromFile(pic);
if (image != null)
{
if (image.Width > 220 || image.Height > 220)
{
System.Drawing.Bitmap final_image = null;
System.Drawing.Graphics graphic = null;
try
{
System.IO.File.Copy(pic, pic + ".bak", true);
int width = image.Width;
int height = image.Height;
int target_width = 220;
int target_height = 220;
int new_width, new_height;
float target_ratio = (float)target_width / (float)target_height;
float image_ratio = (float)width / (float)height;
if (target_ratio > image_ratio)
{
new_height = target_height;
new_width = (int)Math.Floor(image_ratio * (float)target_height);
}
else
{
new_height = (int)Math.Floor((float)target_width / image_ratio);
new_width = target_width;
}
new_width = new_width > target_width ? target_width : new_width;
new_height = new_height > target_height ? target_height : new_height;
final_image = new System.Drawing.Bitmap(target_width, target_height);
graphic = System.Drawing.Graphics.FromImage(final_image);
graphic.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.White), new System.Drawing.Rectangle(0, 0, target_width, target_height));
int paste_x = (target_width - new_width) / 2;
int paste_y = (target_height - new_height) / 2;
graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; /* new way */
//graphic.DrawImage(thumbnail_image, paste_x, paste_y, new_width, new_height);
graphic.DrawImage(image, paste_x, paste_y, new_width, new_height);
image.Dispose();
//string newFileName = System.IO.Path.GetDirectoryName(Server.MapPath(pic)) + "/" + System.IO.Path.GetFileNameWithoutExtension(pic) + "_s" + System.IO.Path.GetExtension(pic);
final_image.Save(pic, System.Drawing.Imaging.ImageFormat.Jpeg);
Response.Write("Fix OK--:" + pic + "
");
Response.Flush();
//return System.IO.Path.GetDirectoryName(pic).Replace("\\", "/") + "/" + System.IO.Path.GetFileNameWithoutExtension(pic) + "_s" + System.IO.Path.GetExtension(pic);
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
finally
{
if (final_image != null) final_image.Dispose();
if (graphic != null) graphic.Dispose();
if (image != null) image.Dispose();
}
}
}
return null;
}
try...catch....finally机制用来释放资源,以保证文件可以在下一次正常调用。
参考链接:http://www.cnblogs.com/wudingfeng/archive/2008/07/24/1250564.html
本文首发:剑锋博客 尊重作者,请保留链接。