views:

119

answers:

1

I have a web application that I upload an image to, the image is subsequently saved to the server's temp folder and displayed via a webhandler on the aspx page.

the code for the aspx:

<img src="PreviewImageQualityHandler.ashx" alt="Picture not loaded" runat="server" id="imagePreview" />

The code for uploading the picture and adding a unique id to the Session:

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>");
    }
}

The webhandler code:

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;
        }
    }
}

My problem is that the webhandler only fires on the first image-upload. If I try and upload a new image, the webhandler never fires.

If I remove everything to do with Session from the webhandler it fires on every single postback, like it should.

If anybody is able to shed some light on my problem, I will be extremely grateful!

Regards

Francis

+2  A: 

OK, a rewrite of my answer (see history if you haven't seen earlier answers). A few notes on your code:

  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.

I know, quite some issues altogether. Go through them one by one and see if it helps. At the very least, your code will become more stable.

Abel
Thanks a LOT!It was indeed the caching of the image that was the problem.This might be a bit "naughty", but "imagePreview.Src = "PreviewImageQualityHandler.ashx" + "?x=" + DateTime.Now;" put me out of my misery!The Response.Write(""); is only for debugging purposes and will be removed.RegardsFrancis
Francis
Glad it works now. Note that even for debugging purposes, `Response.Write` can wreak havoc on your HTML or the way the browser renders it, which can cause so many side effects that it causes more trouble then it solves. Instead, consider using `Debug.Write` for debug output and monitor the debug window of Visual Studio. Also: when going to production, `Debug.Write` will not hamper your code.
Abel
Thanks again! I will certainly re-write my code to use "using". I had already thought about putting a unique ID in a DB, but because of the way the users log in, the user ID isn't available in the mypage.aspx?ID=1234, so my colleague advised me not to do so. The catch all without anything in it is for debugging, and there is a breakpoint there :). I was totally unaware of Debug.Write(). I will use that from now on instead. Thanks a LOT for your time! Regards Francis
Francis