【问题标题】:Out of memory exception in System.Drawing.ImageSystem.Drawing.Image 中的内存不足异常
【发布时间】:2018-10-12 13:47:19
【问题描述】:

我需要调整 3 种不同大小的文件上传图像/图像的大小(每个),并将它们的路径保存到数据库中。

我为此写了 belove 方法。

public void resize(string tempPath,string fname,string extension,int x,int y,string path) {

          System.Drawing.Image img = System.Drawing.Image.FromFile(tempPath);

            using (MemoryStream memory = new MemoryStream())
            {
                Bitmap tnBitmap = new Bitmap(img);
                Graphics tnGraph = Graphics.FromImage(tnBitmap);
                tnGraph.CompositingQuality = CompositingQuality.HighQuality;
                //settings ..
                double ratioX = (double)x / (double)tnBitmap.Width;
                double ratioY = (double)y / (double)tnBitmap.Height;
                double ratio = ratioX < ratioY ? ratioX : ratioY;
                int newHeight = Convert.ToInt32(tnBitmap.Height * ratio);
                int newWidth = Convert.ToInt32(tnBitmap.Width * ratio);    
                int posX = Convert.ToInt32((x - (tnBitmap.Width * ratio)) / 2);
                int posY = Convert.ToInt32((y - (tnBitmap.Height * ratio)) / 2);
                tnGraph.DrawImage(img, posX, posY, newWidth, newHeight);    
                img.Dispose();
                using (FileStream fs = new FileStream(tempPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
                {                      
                    tnBitmap.Save(memory, ImageFormat.Jpeg);
                    byte[] bytes = memory.ToArray();
                    fs.Write(bytes, 0, bytes.Length);
                    fs.Close();
                    try
                    {
                        FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://ftp.address.com/httpdocs/img-cdn" + @"\" + fname + extension);    
                        req.UseBinary = true;
                        req.Method = WebRequestMethods.Ftp.UploadFile;
                        req.Credentials = new NetworkCredential("username", "pw");
                        StreamReader rdr = new StreamReader(memory);

                        rdr.Close();
                        req.ContentLength = memory.ToArray().Length;

                        Stream reqStream = req.GetRequestStream();

                        reqStream.Write(memory.ToArray(), 0, memory.ToArray().Length);
                        reqStream.Close();
                    }
                    catch (WebException e)
                    {
                        String status = ((FtpWebResponse)e.Response).StatusDescription;
                    }                       
                    path = "www.address.com/" + fname + extension;
                }
                memory.Dispose();
                tnBitmap.Dispose();
                tnGraph.Dispose();    
            }

}

方法调用:

public ActionResult addPathFu(string ID){
     List<ProductImage> lPi = new List<ProductImage>();
     string mTempPath = Path.GetTempFileName();
     string sTempPath = Path.GetTempFileName();
     string bTempPath = Path.GetTempFileName();
     string extension = "";
     for (int i = 0; i < Request.Files.Count; i++)
     {            
          ProductImage pi = new ProductImage();
          //bigPath file 
          var bigFileName = $@"{DateTime.Now.Ticks}-b";
          extension = Path.GetExtension(Request.Files[i].FileName);
          Request.Files[i].SaveAs(bTempPath);              
          resize(bTempPath,bigFileName,extension,1500,1500,pi.BigPath);

          //midpath 
          var midFileName = $@"{DateTime.Now.Ticks}-m";
          extension=Path.GetExtension(Request.Files[i].FileName);
          resize(mTempPath, midFileName, extension, 500, 750,pi.MidPath);

          Request.Files[i].SaveAs(mTempPath);

          //smallpath
          var sFileName = $@"{DateTime.Now.Ticks}-s";
          extension = Path.GetExtension(Request.Files[i].FileName);
          Request.Files[i].SaveAs(sTempPath);
          resize(sTempPath, sFileName, extension, 295, 443,pi.SmallPath);

          lPi.Add(pi);
     }
  }

问题是,我第二次在运行时调用这个方法,System.Drawing.Image img = System.Drawing.Image.FromFile(tempPath); 语句抛出错误:

内存不足异常。

我丢弃了所有可丢弃的东西。我也在 web.config 中启用了:

<runtime>
  <gcAllowVeryLargeObjects enabled="true" />
</runtime>

我是否使用了太多内存?我该如何解决这个问题?

【问题讨论】:

  • FromFile() 中的 OOM 通常(误导性地)表明源文件格式存在问题,因此请仔细检查其是否为有效的图像文件。
  • FromFile() 从 C:\\Users\\User\\AppData\\Local\\Temp\\tmpB4C3.tmp 获取文件,我检查了它存在的源文件@AlexK。
  • 您将Image img 作为方法参数,然后将System.Drawing.Image img = System.Drawing.Image.FromFile(tempPath); 在方法主体中。这甚至不会编译。
  • @Zeynep 请检查文件是否为有效图像 - 关于其文件类型,而不是路径是否正确。如果Image.FromFile(string path) 找不到该文件,则会抛出FileNotFoundException。您能否从不会遇到用户访问问题的文件夹中尝试其他图像?
  • 方法调用:resize(bTempPath,bigFileName,extension,1500,1500,pi.BigPath);1500,1500 是图片的新尺寸吗?如果是这样,您只需要构建一个此大小的位图,并使用使用这些新措施调整大小的目标矩形在其中绘制源位图。永远不要使用直接从文件加载的位图。将其更改为:Bitmap img = (Bitmap)Image.FromFile(tempPath).Clone();。或者,Bitmap newBitmap; using (Image img = Image.FromFile(tempPath)) { newBitmap = (Bitmap)img.Clone(); }。否则,GDi+ 将持有该图像的句柄。

标签: c# asp.net-mvc bitmap out-of-memory system.drawing


【解决方案1】:

您的例程声明中的“路径”过多,可能会将其缩短为:

public void resize(string tempPath, string fname, string extension, int x, int y, string path, Image img)

你刚刚编辑了

【讨论】:

  • 此方法声明不反映问题中当前的代码。另外,这不是问题。
  • 他的原始代码是错误的,但是我一发布,他就纠正了他的。这就是为什么我编辑我的帖子并说“你刚刚编辑过”
猜你喜欢
  • 2016-07-27
  • 2010-10-05
  • 1970-01-01
相关资源
最近更新 更多