Sono qui che il mio ingegno termina.Ridimensionamento delle immagini utilizzando il gestore HTTP ASP.Net, alcune immagini non vengono visualizzate
Ho un gestore HTTP (ImageHandler.ashx) che invia le immagini verso il basso (ridimensionate), è un gestore HTTP standard (provato con Reusable true e false) che utilizza Image.GetThumbnailImage per ridimensionare e restituire la miniatura.
Ho un controllo Datalist asp che ha una tabella con un controllo immagine html.
<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>
Come è possibile osservare i parametri di cui il Gestore ha bisogno sono la larghezza e il Percorso immagine.
Questo Datalist è associato a un datatable (ImageData) che fornisce l'elenco di immagini da visualizzare.
Beh, tutto ha un senso fino ad ora, ora ecco il problema - Dire che sto caricando 5 immagini, cioè il mio DataTable ImageData ha 5 righe, è un dato che verranno visualizzate solo 3-4 immagini, le restanti appena arrivato con una X rossa, come quando non hai alcuna immagine. Ora, se si guarda il codice e navigare alla src immagine come -
http://localhost:3540/Scripts/ImageHandler.ashx?width=150&image=Upload/Test123.jpg
vedrete l'immagine, sono tutti lì non ci sono immagini mancanti. Ricarica e sono tornati.
Ho eseguito questo in Firefox e aperto Firebug e quando ho guardato attraverso la scheda Immagini, TUTTE le immagini sono state restituite secondo Firebug (Stato 200 OK e vedo l'immagine nella scheda Risposta), è come il server Web appena non mostra alcuni di loro. Nota che NON sono sempre le immagini che impiegano più tempo a elaborare/caricare quelle mancanti, alcune di quelle casuali.
Cosa potrebbe succedere qui?
Grazie.
MODIFICA 1 - Aggiunta del codice gestore (originale), abbiamo ereditato questo codice. Ho rimosso Caching dal codice qui, ma le miniature FYI una volta generate vengono memorizzate nella cache.
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 Se qualcuno vuole mettere alla prova tutta questa cosa, qui è il codice che raccoglie le immagini a caso da una cartella predefinita per creare il DataTable (ImageData) che l'aspDataList (listImg) è legato a -
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();
Puoi pubblicare il codice gestore? Forse c'è qualcosa lì dentro che a volte restituisce un'immagine vuota. Inoltre, quando dici che le immagini hanno ottenuto 200 stati in Firebug, hanno anche dei contenuti? Dovrebbe dirti il numero di byte restituiti. –
Sì, mostra il contenuto (immagine) e la dimensione. Inoltre, non è sempre la stessa immagine che appare vuota, se dovessi visualizzare lo stesso insieme più volte senza la memorizzazione nella cache, è un'immagine casuale che scompare. Inserirò un po 'il codice del gestore, una volta rimossi i file non necessari da lì. – Rakesh
questa non è una risposta, ma un suggerimento. potresti voler controllare questo pacchetto nuget: http://nuget.org/packages/ImageResizer ha diversi pacchetti extra per ridimensionare gif, ecc. –