上传图像文件时,OutOfMemoryException C#

上传图像文件时,OutOfMemoryException C#,c#,asp.net-mvc,C#,Asp.net Mvc,我一直在制作一幅英勇的形象。当用户上传图像时,我现在检查文件的大小。如果小于1MB,我会检查文件是否为图像类型。最后,我将图像调整到合适的大小,并创建图像的小缩略图。但是,自从添加代码来检查类型以来,我一直在体验OutOfMemoryException和OutOfMemoryException 以下是我的控制器方法: [AcceptVerbs(HttpVerbs.Post)] public ActionResult Upload(Image image, HttpPost

我一直在制作一幅英勇的形象。当用户上传图像时,我现在检查文件的大小。如果小于1MB,我会检查文件是否为图像类型。最后,我将图像调整到合适的大小,并创建图像的小缩略图。但是,自从添加代码来检查类型以来,我一直在体验OutOfMemoryException和OutOfMemoryException

以下是我的控制器方法:

        [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Upload(Image image, HttpPostedFileBase ImageFile)
    {

        if (ImageFile.ContentLength > 0)
        {
            // Get the size in bytes of the file to upload.
            int fileSize = ImageFile.ContentLength;

            // Allow only files less than 1,048,576 bytes (approximately 1 MB) to be uploaded.
            if (fileSize < 1048576)
            {
                string fileclass = "";

                using (BinaryReader r = new BinaryReader(ImageFile.InputStream))
                {
                    byte buffer = r.ReadByte();
                    fileclass = buffer.ToString();
                    buffer = r.ReadByte();
                    fileclass += buffer.ToString();
                    r.Close();
                }

                switch (fileclass)
                {
                    case "7137":
                    case "255216":
                    case "13780":
                        try
                        {
                            string path = Server.MapPath("~/Uploads/");

                            ImageFile.SaveAs(path + ImageFile.FileName);

                            ResizeImageHelper resizeImageHelper = new ResizeImageHelper();
                            resizeImageHelper.ResizeImage(path + ImageFile.FileName, path + ImageFile.FileName, 640, 480, false);
                            resizeImageHelper.ResizeImage(path + ImageFile.FileName, path + "thumb" + ImageFile.FileName, 74, 74, false);

                            image.imageLocation = ImageFile.FileName;
                            image.imageThumb = "thumb" + ImageFile.FileName;

                            imageRepository.Add(image);
                            imageRepository.Save();

                            return RedirectToAction("Index", "Home");
                        }
                        catch (Exception ex)
                        {
                            return View("Error");
                        }
                }

            }
            else
            {
                //If file over 1MB
                return View("Error");
            }
        }
        else
        {
            //If file not uploaded
            return View("Error");
        }

        return View("Error");
    }
我假设这不会在第一次运行时发生,但是在一段时间之后。这是正确的吗

编辑:删除了不正确的假设,但
IDisposable仍然存在问题


您没有处理NewImage,这将导致生产中出现问题

我通常会说“只是使用一个using”,但try/finally是一样的。根据您的判断,重构到我们这里来

System.Drawing.Image NewImage = null;
System.Drawing.Image FullsizeImage = null;

try
{
    FullsizeImage = System.Drawing.Image.FromFile(OriginalFile);

     [... snip ... ]

    NewImage = FullsizeImage.GetThumbnailImage(NewWidth, NewHeight, null, IntPtr.Zero);

    // Clear handle to original file so that we can overwrite it if necessary
    FullsizeImage.Dispose();

    // Save resized picture
    NewImage.Save(NewFile);
}
finally
{
    if (FullsizeImage != null)
        FullsizeImage.Dispose();
    if (NewImage != null)
        NewImage.Dispose();
}

好了,伙计们,在发现这部分代码后,问题出在:

using (BinaryReader r = new BinaryReader(ImageFile.InputStream))
            {
                byte buffer = r.ReadByte();
                fileclass = buffer.ToString();
                buffer = r.ReadByte();
                fileclass += buffer.ToString();
                r.Close();

            }
我把它改成这样:

string fileclass = ImageFile.ContentType.ToString();
并将我的switch语句更改为:

switch (fileclass)
                {
                    case "image/jpg":
                    case "image/jpeg":
                    case "image/png":
                    case "image/gif":
                        try

我还实施了罗伯特的建议。但是,作为.NET的新手,我不确定这种检查文件类型的方法是否与以前的方法一样准确?我的研究似乎表明,即使up loader更改了扩展名(例如,将example.exe重命名为example.jpg),previous也可以发现文件类型。我不确定使用提供的.NET功能是否仍然可以实现相同的功能

异常发生在哪里?我刚刚计算出它发生在这一行:System.Drawing.Image FullsizeImage=System.Drawing.Image.FromFile(原始文件);然而,在我开始把所有的检查放在适当的位置之前,这是有效的。在第一次运行时不会发生这种情况。查看此行ImageFile.SaveAs(path+ImageFile.FileName)上的逻辑;文件未正确保存在文件夹中。它显示为0字节。我明白了。您的图像大小调整代码仍然缺失,它是可识别的。请释放调用。对于任何IDisposable对象,您都应该养成使用该对象来处理.Dispose()调用的习惯。使用(Image newImage=FullSizeImage.GetThumbnailImage(newWidth,newHeight,null,IntPtr.Zero){//do stuff with newImage}//结束作用域自动处理object@Michael是的,这也是我写的,但别担心-所写的try/finally代码相当于编译器将使用using块生成的代码。请看,我一时记不起来了,但是请求的
ContentType
可以由执行上载的客户端设置,如果在这种情况下,被恶意客户端欺骗。文件扩展名也是如此。因此我可能不想完全信任他们。您还可以检查
System.Drawing.Image
实例的属性
RawFormat
的类型为
System.Drawing.Imaging.ImageFormat
,并将其与静态实例进行比较。例如
如果(UploadeImage.RawFormat==ImageFormat.Jpeg).
string fileclass = ImageFile.ContentType.ToString();
switch (fileclass)
                {
                    case "image/jpg":
                    case "image/jpeg":
                    case "image/png":
                    case "image/gif":
                        try