我正在尝试编写一些代码,一旦用户点击某个删除按钮,该代码就会从硬盘上删除图像。有时我会得到以下异常,有时候我没有。当我真的这样做时,如果我再次尝试删除它,它大部分时间都可以工作。
这是一个例外:
System.IO.IOException:进程无法访问该文件,因为它 正在被另一个进程使用。
我想我应该提供一些有关正在发生的事情的细节:
我不确定如何解决此问题,因为该异常未提供有关哪个其他进程保留在文件中的任何信息。有什么想法吗?
更新
public byte[] ResizeImageToBytes(string path, int size, string name)
{
var newImage = Image.FromFile(path);
int newWidth; int newHeight;
if (size == 470)
{
if (newImage.Height != 250)
{
newWidth = (int)Math.Round(newImage.Width * (100 / (newImage.Height / 250)) * 0.01);
newHeight = 250;
}
else
{
newWidth = newImage.Width;
newHeight = newImage.Height;
}
}
else
{
if (newImage.Width > newImage.Height)
{
newWidth = size;
newHeight = newImage.Height*size/newImage.Width;
}
else
{
newWidth = newImage.Width*size/newImage.Height;
newHeight = size;
}
}
var thumb = new Bitmap(newWidth, newHeight);
var gfx = Graphics.FromImage(thumb);
gfx.CompositingQuality = CompositingQuality.HighQuality;
gfx.SmoothingMode = SmoothingMode.HighQuality;
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
var rect = new Rectangle(0, 0, newWidth, newHeight);
gfx.DrawImage(newImage, rect);
var ms = new MemoryStream();
thumb.Save(ms, newImage.RawFormat);
return ms.GetBuffer();
}
public void SaveImage(byte[] toSave, string path)
{
using (var ms = new MemoryStream())
{
ms.Write(toSave, 0, toSave.Length);
using(var theImage = Image.FromStream(ms))
{
theImage.Save(path);
}
}
}
[HttpPost]
public ActionResult Upload()
{
var newFile = System.Web.HttpContext.Current.Request.Files["Filedata"];
string guid = Guid.NewGuid() + newFile.FileName;
string itemImagesFolder = Server.MapPath(Url.Content("~/Content/ItemImages/"));
string fileName = itemImagesFolder + "originals/" + guid;
newFile.SaveAs(fileName);
string finalPath;
foreach (var dim in ImageDimensionsList.Options)
{
var bytes = _imageService.ResizeImageToBytes(fileName, dim.Width, guid);
finalPath = itemImagesFolder + dim.Title + "/" + guid;
_imageService.SaveImage(bytes, finalPath);
}
return Content(guid);
}
答案 0 :(得分:5)
您没有在ResizeImageToBytes
方法中处置您正在使用的任何可支配资源。这会在应用程序中留下泄漏的句柄,当然还有锁定的文件。试试这个:
public byte[] ResizeImageToBytes(string path, int size, string name)
{
using (var newImage = Image.FromFile(path))
{
int newWidth; int newHeight;
if (size == 470)
{
if (newImage.Height != 250)
{
newWidth = (int)Math.Round(newImage.Width * (100 / (newImage.Height / 250)) * 0.01);
newHeight = 250;
}
else
{
newWidth = newImage.Width;
newHeight = newImage.Height;
}
}
else
{
if (newImage.Width > newImage.Height)
{
newWidth = size;
newHeight = newImage.Height * size / newImage.Width;
}
else
{
newWidth = newImage.Width * size / newImage.Height;
newHeight = size;
}
}
using (var thumb = new Bitmap(newWidth, newHeight))
using (var gfx = Graphics.FromImage(thumb))
{
gfx.CompositingQuality = CompositingQuality.HighQuality;
gfx.SmoothingMode = SmoothingMode.HighQuality;
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
var rect = new Rectangle(0, 0, newWidth, newHeight);
gfx.DrawImage(newImage, rect);
using (var ms = new MemoryStream())
{
thumb.Save(ms, newImage.RawFormat);
return ms.GetBuffer();
}
}
}
}
就你的SaveImage
方法而言,这个方法对我来说似乎是多余的,因为它已经存在于.NET框架中。它被称为File.WriteAllBytes:
public void SaveImage(byte[] toSave, string path)
{
File.WriteAllBytes(path, toSave);
}
答案 1 :(得分:0)
在上传例程中,您是否在文件阅读器周围使用using
语句?如果不是,那么文件资源不会返回到OS,因此它仍然被“使用”。
答案 2 :(得分:0)
要查找有关其他进程保留在文件中的信息,您应该使用ProcessExplorer(sysinternals.com)之类的工具。它具有这个方便的搜索功能(查找>查找句柄或DLL),您可以在其中输入类似文件名的字符串,它将搜索所有句柄并告诉您哪个进程的句柄处于打开状态。
通常当我遇到像您这样的意外错误时,这是我去的第一个地方。
希望这有帮助,
约翰