Webhandler在回发时未触发

3
我有一个网络应用程序,我上传一张图片,然后将该图片保存到服务器的临时文件夹中,并通过aspx页面上的WebHandler显示。
aspx的代码如下:
<img src="PreviewImageQualityHandler.ashx" alt="Picture not loaded" runat="server" id="imagePreview" />

上传图片并在会话中添加唯一标识符的代码:
protected void uploadButton_Click(object sender, EventArgs e)
{
    if (FileUploadControl.FileName.EndsWith(".jpg") || FileUploadControl.FileName.EndsWith(".jpeg"))
    {
        string tempFileName = Path.GetTempFileName();
        FileUploadControl.SaveAs(tempFileName);
        Session["tempName"] = tempFileName;
        Response.Write(Session["tempName"]);
        fileName = FileUploadControl.FileName;
    }
    else
    {
        Response.Write("<script>alert('Please select a .jpg/.jpeg image to upload')</script>");
    }
}

网络处理程序代码:
public class PreviewImageQualityHandler : IHttpHandler, IRequiresSessionState
{   
    public void ProcessRequest(HttpContext context)
    {
        try
        {
            if (context.Session.Count > 0)
            {
                string sessID = context.Session["tempName"].ToString();
                Bitmap bmp = (Bitmap)System.Drawing.Image.FromFile(sessID);
                context.Response.ContentType = "image/jpg";
                MemoryStream ms = new MemoryStream();
                bmp.Save(ms, ImageFormat.Bmp);
                byte[] b = ms.ToArray();
                context.Response.OutputStream.Write(b, 0, b.Length);
            }
        }
        catch(Exception ex) 
        { 

        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

我的问题是WebHandler仅在第一次上传图像时触发。如果我尝试上传新图像,则WebHandler永远不会触发。
如果我从WebHandler中删除与Session有关的所有内容,它就会在每个postback上触发,就像它应该做的那样。
如果有人能够解决我的问题,我将非常感激!
问候
弗朗西斯

很遗憾,Francis,我似乎无法复制您所看到的错误。也许是您发布的代码之外的某些东西引起了问题?我猜测可能是缓存的问题。不确定是什么或在哪里。 - Adrian Clark
1个回答

4

好的,我会对我的答案进行重写(如果您还没有看到之前的答案,请查看历史记录)。以下是关于您的代码的一些注意事项:

  1. Don't use Response.Write. You cannot determine when it will write and often you won't see it in the browser. Use an asp:Literal control or an asp:Label instead. Related with current issue because: if you don't see it in the browser, perhaps you think nothing happens.

  2. You don't safe-guard the opening / closing of the file stream. Add a using-block around it so that the stream is properly closed and disposed off. The way you have it currently, the file will remain open as long as the thread is alive and that's pretty long.

    using(Bitmap bmp = (Bitmap)System.Drawing.Image.FromFile(sessID))
    {
         //.. your code...
         using(MemoryStream.... etc)
         {
             ....
         }
    }
    

    The problem with not-closing: you will not be able to write a new file to the same location next time, you may not be able to open it for reading and you'll quite quickly run out of available file handlers when your code goes live.

  3. Not sure what you expect from the session. But it is probably better to use some ID with the picture, store that in the database with the current user info, and add that as a request querystring to the image URL. That way, you can't get into trouble with session issues:

    <img src="myimage.ashx?id=1234" />
    

    Either, 1234 refers to something on disk, or it refers to something in the database, which in turn refers to something on disk (much safer).

  4. If you are unsure whether the browser resends the request, use FireBug with FireFox, which gives you full details of the HTTP requests and responses. If you use the same name, the browser will (unless you're in debug mode) not send a new request each time.

  5. You're using a catch-all exception handler. Write something there, or place a breakpoint at that position. A catch-all exception handler is very dangerous: many exceptions will never be seen. Quite possibly, your current code throws an exception (see point 2 above) and that's it. Remove the exception handler and the exception be caught by your Visual Studio debugger so you know what's up.

我知道,一些问题同时出现。逐一解决它们,看看是否有帮助。至少,你的代码将变得更加稳定。


非常感谢!问题确实是图像缓存引起的。这可能有点“淘气”,但是“imagePreview.Src =“PreviewImageQualityHandler.ashx”+”?x=”+ DateTime.Now;”让我解脱了!Response.Write(“”)仅用于调试目的,将被删除。问候弗朗西斯 - Francis
很高兴现在它可以工作了。请注意,即使是为了调试目的,Response.Write 也可能会对您的 HTML 或浏览器呈现方式造成严重影响,这可能会导致许多副作用,从而引起更多麻烦。相反,考虑使用 Debug.Write 进行调试输出并监视 Visual Studio 的调试窗口。此外:当进入生产环境时,Debug.Write 不会妨碍您的代码。 - Abel
再次感谢!我一定会重写我的代码来使用“using”。我已经考虑过在数据库中放置唯一的ID,但由于用户登录的方式,用户ID在mypage.aspx?ID=1234中不可用,所以我的同事建议我不要这样做。没有任何内容的catch all是为了调试,并且在那里有一个断点:)。我完全不知道Debug.Write()。从现在开始我会使用它。非常感谢您的时间!问候Francis - Francis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接