Question

I'm at my wits end here.

I've a HTTP Handler (ImageHandler.ashx) that sends down images (resized), its a standard HTTP handler (tried this with Reusable true and false) that uses the Image.GetThumbnailImage to resize and return the thumbnail.

I've an asp Datalist control which has a table with a html image control.

     <asp:DataList ID="listImg" runat="server" RepeatColumns="4" RepeatDirection="Horizontal"
        ShowFooter="false" ShowHeader="false">
        <ItemTemplate>
            <table width="220px">
                <tr width="100%">
                    <td>
                        <img src="Scripts/ImageHandler.ashx?width=125&image=Upload/<%# DataBinder.Eval(Container.DataItem, "photo") %>"                              
                    </td>
                </tr>
            </table>
        </ItemTemplate>
    </asp:DataList>

As you can see the parameters the Handler needs are the width and the Image path.

This Datalist is bound to a datatable (ImageData) which provides the list of images to be displayed.

Well all makes sense so far, now here is the issue - Say I'm loading 5 images, i.e. my ImageData DataTable has 5 rows, it is a given that only 3-4 images will be displayed, the remaining ones just come up with a red X, like when you've no image. Now if you look at the code and navigate to the image src like -

    http://localhost:3540/Scripts/ImageHandler.ashx?width=150&image=Upload/Test123.jpg

you'll see the image, they're all there no missing images. Reload and they're back.

I ran this in Firefox and opened up Firebug and when I looked through the Images tab, ALL the images were returned according to Firebug (Status 200 OK and I see the Image in the Response tab), it's like the Webserver just does not display some of them. Note that it is NOT always the images that took the longest to process/load that were missing, its some random ones.

What could be going on here?

Thank you.

EDIT 1- Adding the Handler Code (original), we inherited this code. I've removed Caching from the code here, but FYI thumbnails once generated are cached.

    public class ImageHandler : IHttpHandler{
public int _width;
public int _height;
public int _percent;
public string imageURL;


public void ProcessRequest(HttpContext context)
{
    try
    {
        Bitmap bitOutput;

        string appPath = Convert.ToString(System.Configuration.ConfigurationManager.AppSettings["ImagePath"]);

        String strArquivo = appPath + context.Request.QueryString["image"].Replace("/", "\\");

        if (!(String.IsNullOrEmpty(context.Request["width"])))
        {
            Bitmap bitInput = GetImage(context);

           if (SetHeightWidth(context, bitInput))
            { bitOutput = ResizeImage(bitInput, _width, _height, _percent); }
            else { bitOutput = bitInput; }

            context.Response.ContentType = "image/jpeg";
            bitOutput.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
        }

        return;

    }
    catch (Exception ex) { /*HttpContext.Current.Response.Write(ex.Message);*/ }
}


/// <summary>
/// Get the image requested via the query string. 
/// </summary>
public Bitmap GetImage(HttpContext context)
{
    try
    {
        if (context.Cache[("ImagePath-" + context.Request.QueryString["image"])] == null)
        {
            string appPath = Convert.ToString(System.Configuration.ConfigurationManager.AppSettings["ImagePath"]);

            appPath = appPath + context.Request.QueryString["image"].Replace("/", "\\");
            Bitmap bitOutput;
            imageURL = appPath;


            bitOutput = new Bitmap(appPath);
            return bitOutput;
        }
        else
        {
            return (Bitmap)context.Cache[("ImagePath-" + context.Request.QueryString["image"])];
        }

    }
    catch (Exception ex) { throw ex; }
}    


/// <summary>
/// Set the height and width of the handler class.
/// </summary>
public bool SetHeightWidth(HttpContext context, Bitmap bitInput)
{
    try
    {
        double inputRatio = Convert.ToDouble(bitInput.Width) / Convert.ToDouble(bitInput.Height);

        if (!(String.IsNullOrEmpty(context.Request["width"])) && !(String.IsNullOrEmpty(context.Request["height"])))
        {
            _width = Int32.Parse(context.Request["width"]);
            _height = Int32.Parse(context.Request["height"]);
            return true;
        }
        else if (!(String.IsNullOrEmpty(context.Request["width"])))
        {
            _width = Int32.Parse(context.Request["width"]);
            _height = Convert.ToInt32((_width / inputRatio));
            if (_width == 400 &&_height > 500)
            {
                _height = 500;
                _width = Convert.ToInt32(500 * inputRatio);
            }
            else if (_width == 125 && _height > 200)
            {
                _height = 200;
                _width = Convert.ToInt32(200 * inputRatio);
            }
            return true;
        }
        else if (!(String.IsNullOrEmpty(context.Request["height"])))
        {
            _height = Int32.Parse(context.Request["height"]);
            _width = Convert.ToInt32((_height * inputRatio));
            return true;
        }
        else if (!(String.IsNullOrEmpty(context.Request["percent"])))
        {
            _height = bitInput.Height;
            _width = bitInput.Width;
            _percent = Int32.Parse(context.Request["percent"]);
            return true;
        }
        else
        {
            _height = bitInput.Height;
            _width = bitInput.Width;
            return false;
        }

    }
    catch (Exception ex) { throw ex; }
}

/// <summary>
/// Resizes bitmap using high quality algorithms.
/// </summary>
public static Bitmap ResizeImage(Bitmap originalBitmap, int newWidth, int newHeight, int newPercent)
{
    try
    {
        if (newPercent != 0)
        {
            newWidth = Convert.ToInt32(originalBitmap.Width * (newPercent * .01));
            newHeight = Convert.ToInt32(originalBitmap.Height * (newPercent * .01));
        }

        Bitmap inputBitmap = originalBitmap;
        Bitmap resizedBitmap = new Bitmap(newWidth, newHeight, PixelFormat.Format64bppPArgb);

        Graphics g = Graphics.FromImage(resizedBitmap);
        g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        Rectangle rectangle = new Rectangle(0, 0, newWidth, newHeight);
        g.DrawImage(inputBitmap, rectangle, 0, 0, inputBitmap.Width, inputBitmap.Height, GraphicsUnit.Pixel);
        g.Dispose();

        return resizedBitmap;

    }
    catch (Exception ex) { throw ex; }
}


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

EDIT 2 If someone wishes to test this whole thing out, here is the code that picks up images at random from a predefined folder to create the DataTable (ImageData) that the aspDataList (listImg) is bound to -

        System.IO.DirectoryInfo dirInfo = new System.IO.DirectoryInfo(Server.MapPath("Upload"));
        System.IO.FileInfo[] files = dirInfo.GetFiles();

        int fileCount = files.Length;

        System.Data.DataTable ImageData = new System.Data.DataTable();
        System.Data.DataColumn dCol = new System.Data.DataColumn("photo");
        ImageData.Columns.Add(dCol);


        System.Random rnd = new Random();
        int nxtNumber = 0;

        System.Data.DataRow dRow = null;

        string fileName = string.Empty;

        for (int i = 0; i < 20; i++)
        {
            dRow = ImageData.NewRow();
            nxtNumber = rnd.Next(fileCount);
            while (!files[nxtNumber].Extension.Equals(".jpg"))
            {
                nxtNumber = rnd.Next(fileCount);
            }
            fileName = files[nxtNumber].Name;

            dRow["photo"] = fileName;

            ImageData.Rows.Add(dRow);
        }
        listImg.DataSource = ImageData;
        listImg.DataBind();
Was it helpful?

Solution 3

Well here is the funny thing - the same code on the server behaves in a more predictable manner, I may still have a couple of missing images, but now it is like 1 missing from say 30-40 on average versus 1 from every 5 in my local environment. Since these requests were asynchronous could it have something to do with the actual cpu of the machine it was running on, the server was just better adapted to deal with multiple requests versus my measly laptop?

Either ways I've modified the code, so at this point there is no re-sizing involved, the handler code just fetches re-sized images and all is well at this point.

Thank you all for your inputs.

OTHER TIPS

try to encode querystring of url, for ex:

http://localhost:3540/Scripts/ImageHandler.ashx?width=150&image=Upload/Test123.jpg

urlencode to

http://localhost:3540/Scripts/ImageHandler.ashx?width%3D150%26image%3DUpload%2FTest123.jpg

I presume your actual code includes the /> at the end of the img tag??? If not you could try adding this first and retesting.

Not really an answer but you could try changing the img tag to an asp:Label and displaying the filename as text rather than displaying the image just to see if the datatable is being constructed correctly. As you are able to see the images when accessing the image handler directly I would say it has something to do with the datatable construction in the codebehind.

When ever I have done anything similar I usually store the images in the SQL DB and use the image handler to return the image with the record id in the query string. This means you are returning a existing table of records rather than having to create one based on the contents of a folder.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top