【发布时间】: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