【问题标题】:Image Handler returning same image after multiple calls in asp.net在 asp.net 中多次调用后图像处理程序返回相同的图像
【发布时间】:2012-12-09 19:12:51
【问题描述】:

我正在尝试为我的网站创建一个图像处理程序,基本的调整大小、旋转和裁剪工作,并且在网站上显示正常但是我尝试通过将文件保存在 /chached/filename.png 中来为处理程序添加缓存但出于某种原因添加缓存后,图像处理程序返回错误的图像。例如,我有一个项目列表页面,其中调整大小的项目图像显示在表格视图中,但是前 4 个项目显示为具有相同的图像,然后接下来的 4 个显示为不同的图像,但都相同,等等。

我感觉这是由于 response.outputstream 造成的,但我不确定,因为在调用下一个图像之前似乎没有足够的时间来完成第一个图像。

以防万一,完整代码可在此处获得:http://pastebin.com/BNyDfqPy

我的流程请求方法如下:

public void ProcessRequest(HttpContext context)
{
    // Settings and locations
    appPath = HttpContext.Current.Request.PhysicalApplicationPath;
    location = context.Request.QueryString["image"];
    cacheLocation = Path.GetDirectoryName(appPath + location) + "/Cached/";

    // Input/Output
    Bitmap bitOutput;
    Bitmap bitInput = GetImage(context);

    if (cacheAvailable)
    {
        bitOutput = bitInput;
    }
    else
    {
        try
        {
            Boolean crop = false;

            if (context.Request["type"] == "crop")
            {
                crop = true;
            }

            bitInput = RotateFlipImage(context, bitInput);

            if (hasSetSize)
            {
                Int32 x = String.IsNullOrEmpty(context.Request["x"]) ? 0 : Int32.Parse(context.Request["x"]);
                Int32 y = String.IsNullOrEmpty(context.Request["y"]) ? 0 : Int32.Parse(context.Request["y"]);

                bitOutput = ResizeImage(bitInput, _width, _height, crop, x, y);

                bitOutput.Save(cacheLocation + cacheKey + ".png", System.Drawing.Imaging.ImageFormat.Png);
            }
            else
            {
                throw new Exception();
            }
        }
        catch (Exception)
        {
            bitOutput = bitInput;
        }
    }


    context.Response.Clear();
    context.Response.Cache.SetNoStore();
    context.Response.ContentType = "image/png";

    using (MemoryStream ms = new MemoryStream())
    {
        bitOutput.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        ms.WriteTo(context.Response.OutputStream);
    }
    //bitOutput.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Png);

    bitOutput.Dispose();
    bitInput.Dispose();
    context.Response.Flush();

    return;        
}

我用这个得到图像:

public Bitmap GetImage(HttpContext context)
{
    // Get location
    Bitmap bitOutput = null;

    try
    {
        if (!String.IsNullOrEmpty(location))
        {
            Image image = Image.FromFile(appPath + location);
            bitOutput = new Bitmap(image);
            hasSetSize = SetHeightWidth(context, bitOutput);

            if (!System.IO.Directory.Exists(cacheLocation))
            {
                System.IO.Directory.CreateDirectory(cacheLocation);
            }

            // Generate cache key
            cacheKey = "imagehandler_" + _width + "x" + _height + "_" + context.Request["RotateFlip"] + context.Request["type"];

            if (File.Exists(cacheLocation + cacheKey + ".png"))
            {
                image = Image.FromFile(cacheLocation + cacheKey + ".png");
                bitOutput = new Bitmap(image);
                cacheAvailable = true;
            }
        }
        else
        {
            throw new Exception("Can't load original or save to cache, check directory permissions!");
        }
    }
    catch (Exception)
    {
        Image image = Image.FromFile(appPath + noImageUrl);
        bitOutput = new Bitmap(image);
    }

    return bitOutput;
}

我也有isReusable 设置如下:

public bool IsReusable
{
    get
    {
        return false;
    }
}

输出如下图所示,每个项目都有不同的图像集,但它们要么显示与上一个/下一个图像相同的图像,要么是自己的图像(这是我想要的)或占位符图像:

【问题讨论】:

    标签: c# asp.net image caching handler


    【解决方案1】:

    正如我看到的代码,您可能对 cacheAvailable 使用了静态变量,并且 after 设置为 true 不会在下次调用时返回 false。

    因此,请检查您何时将 cacheAvailable false 作为每个请求的默认值。

    【讨论】:

    • 我已经从静态中删除了 cacheAvailable 并将其作为变量放在 getImage() 中,仍然是相同的输出,有什么想法吗?
    • @LukeAlderton 你能给出完整的页面代码吗?或者在处理程序的调用中简单地使 cacheAvailable=false
    • @LukeAlderton 我看的很快,我说你要删除所有 4 个静态的!试试看。我对cacheAvailable 的预测是正确的:)
    • 啊,做到了,我必须清除缓存,然后重新加载页面,现在一切正常,非常感谢,你知道当你编码几个小时后是怎样的最简单的事情会让你陷入困境! ;)
    【解决方案2】:

    首先,除非您真的希望您的处理程序能够反复使用同一个实例,否则请让IsReusable 返回 false。

    如果您不想这样做,请删除 cacheAvailable 类级别变量,更改此:

    // Input/Output
    Bitmap bitOutput;
    Bitmap bitInput = GetImage(context);
    

    到这里:

    // Input/Output
    Bitmap bitOutput;
    bool cacheAvailable;
    Bitmap bitInput = GetImage(context, out cacheAvailable);
    

    并修改GetImage 看起来像这样

    public Bitmap GetImage(HttpContext context, out bool cacheAvailable)
    {
        // Get location
        Bitmap bitOutput = null;
        cacheAvailable = false;
    
        try
        {
            if (!String.IsNullOrEmpty(location))
            {
                Image image = Image.FromFile(appPath + location);
                bitOutput = new Bitmap(image);
                hasSetSize = SetHeightWidth(context, bitOutput);
    
                if (!System.IO.Directory.Exists(cacheLocation))
                {
                    System.IO.Directory.CreateDirectory(cacheLocation);
                }
    
                // Generate cache key
                cacheKey = "imagehandler_" + _width + "x" + _height + "_" + context.Request["RotateFlip"] + context.Request["type"];
    
                if (File.Exists(cacheLocation + cacheKey + ".png"))
                {
                    image = Image.FromFile(cacheLocation + cacheKey + ".png");
                    bitOutput = new Bitmap(image);
                    cacheAvailable = true;
                }
            }
            else
            {
                throw new Exception("Can't load original or save to cache, check directory permissions!");
            }
        }
        catch (Exception)
        {
            Image image = Image.FromFile(appPath + noImageUrl);
            bitOutput = new Bitmap(image);
        }
    
        return bitOutput;
    }
    

    【讨论】:

    • 感谢您的帮助,但据我所知 isResuable 设置为返回 false,我已更新我的代码 sn-ps 以包含此内容,但是我遵循了您对代码的建议更新和它仍然给我相同的输出。有什么想法吗?
    猜你喜欢
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-24
    • 2020-12-27
    • 2016-05-23
    • 1970-01-01
    • 2017-05-28
    相关资源
    最近更新 更多