HttpHandler for Images in ASP .NET 2.0
Http Handler:
Http Handler is a class that is responsible for rendering a particular resource, or a particular type of resource.
Http Handlers are somewhat similar to ISAPI Extensions. If implements, it behaves like a filter between Web Server and the Client. Whenever client makes a request to the server, it goes through the Filter and performs operations as per our requirement.
HTTP handlers has following two methods:
1) ProcessRequest: called to process http requests and
2) IsReusable which indicates whether this instance of http handler can be reused for fulfilling another requests of the same type.
What does this code do?
It accepts the request from the client as virtual URL. It picks up the image (as desired in the URL "http://localhost/pictureserver/1.jpg") from original image folder. It resizes the image in desired size and returns it. The resized image is stored for future use. On subsequent requests for same image, it picks up stored image and returns it back. All information like physical path of the original and processed folders is fetched from web.config of the application. I know it is bit complicated but there is a saying “Try, try, try, and keep on trying is the rule that must be followed to become an expert in anything." And it fits here perfectly. So Best of Luck dudes….
Step 1 : Create a Class Library in C# and Paste the following code and name it “Handler.cs”
using System;
using System.Web;
using System.Drawing;
using System.Configuration;
using System.IO;
using System.Data;
using MySql.Data.MySqlClient;
using MySql.Data.Types;
using System.Web.Security;
namespace Handler
{
public class ImageHttpHandler: IHttpHandler
{
#region IHttpHandler Members
public bool IsReusable
{
get
{
return false;
}
}
public void ProcessRequest(HttpContext context)
{
String[] ValidDirectoriesArray = new String[3] { "S", "M", "L" };
Boolean SentJpg = false;
HttpRequest app = context.Request;
String[] FilePathArray = app.FilePath.Split('\\', '/');
if (FilePathArray.Length > 2) // need at least /directory/imagename.jpg
{
String FileName = FilePathArray[FilePathArray.Length - 1].ToUpper();
String DirectoryName = FilePathArray[FilePathArray.Length - 2].ToUpper();
//Make sure the file name is at least long enough for X.JPG
if (FileName.Length > 4)
{
if (FileName.Substring(FileName.Length - 4, 4) == ".JPG")
{
if (Array.IndexOf(ValidDirectoriesArray, DirectoryName) > -1)
{
if (GetRealPathAndFileName(imageFileName, DirectoryName))
{
context.Response.OutputStream.Write(imgData, 0, imgData.Length);
}
} // if not one of the pre-defined directory names... don't do anything
} // if not .JPG... don't do anything
} // if file length too short, don't do anything
} // if not enough nodes in the URL for directory and file name, don't do anything
}
#endregion
#region Methods
private bool GetRealPathAndFileName(String VirtualFileName, String VirtualDirectory)
{
if (VirtualDirectory == "S")
{
#region S
string ImageDirectory; //Path for processed images
string ImageDirectoryXLarge; //Path of Raw Image
string NoImageFile; //No Image
Int32 HeightPixels; //Image Height
Int32 WidthPixels; //Image Width
ImageDirectory = System.Configuration.ConfigurationManager.AppSettings["ImageDirectoryS"];
ImageDirectoryXLarge = System.Configuration.ConfigurationManager.AppSettings["ImageDirectoryXLarge"];
HeightPixels = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["HeightPixelsS"]);
WidthPixels = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["WidthPixelsS"]);
NoImageFile = System.Configuration.ConfigurationManager.AppSettings["NoImageFileS"];
if (File.Exists(ImageDirectory + VirtualFileName)) //Check Processed Image is there in the Folder.
{
FromFile(ImageDirectory + VirtualFileName);
return true; //Image Processed
}
else
{
if (File.Exists(ImageDirectoryXLarge + VirtualFileName)) //Check Raw Image is there in Folder
{
SetSize(ImageDirectoryXLarge, ImageDirectory, VirtualFileName, WidthPixels, HeightPixels);
return true; //Image Processed
}
else //Raw Image is not in folder, therefore, show "No Image"
{
if (File.Exists(NoImageFile))
{
FromFile(NoImageFile);
return true; //Image Processed
}
else
{
return false; //No Path/Image Found
}
}
}
#endregion
}
else if (VirtualDirectory == "M")
{
#region M
string ImageDirectory; //Path for processed images
string ImageDirectoryXLarge; //Path of Raw Image
string NoImageFile; //No Image
Int32 HeightPixels; //Image Height
Int32 WidthPixels; //Image Width
ImageDirectory = System.Configuration.ConfigurationManager.AppSettings["ImageDirectoryM"];
ImageDirectoryXLarge = System.Configuration.ConfigurationManager.AppSettings["ImageDirectoryXLarge"];
HeightPixels = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["HeightPixelsM"]);
WidthPixels = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["WidthPixelsM"]);
NoImageFile = System.Configuration.ConfigurationManager.AppSettings["NoImageFileM"];
if (File.Exists(ImageDirectory + VirtualFileName)) //Check Processed Image is there in the Foder.
{
FromFile(ImageDirectory + VirtualFileName);
return true; //Image Processed
}
else
{
if (File.Exists(ImageDirectoryXLarge + VirtualFileName)) //Check Raw Image is there in Folder
{
SetSize(ImageDirectoryXLarge, ImageDirectory, VirtualFileName, WidthPixels, HeightPixels);
return true; //Image Processed
}
else //Raw Image is not in folder, therefore, show "No Image"
{
if (File.Exists(NoImageFile))
{
FromFile(NoImageFile);
return true; //Image Processed
}
else
{
return false; //No Path/Image Found
}
}
}
#endregion
}
else
{
#region L
string ImageDirectory; //Path for processed images
string ImageDirectoryXLarge; //Path of Raw Image
string NoImageFile; //No Image
Int32 HeightPixels; //Image Height
Int32 WidthPixels; //Image Width
ImageDirectory = System.Configuration.ConfigurationManager.AppSettings["ImageDirectoryL"];
ImageDirectoryXLarge = System.Configuration.ConfigurationManager.AppSettings["ImageDirectoryXLarge"];
HeightPixels = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["HeightPixelsL"]);
WidthPixels = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["WidthPixelsL"]);
NoImageFile = System.Configuration.ConfigurationManager.AppSettings["NoImageFileL"];
if (File.Exists(ImageDirectory + VirtualFileName)) //Check Processed Image is there in the Foder.
{
FromFile(ImageDirectory + VirtualFileName);
return true; //Image Processed
}
else
{
if (File.Exists(ImageDirectoryXLarge + VirtualFileName)) //Check Raw Image is there in Folder
{
SetSize(ImageDirectoryXLarge, ImageDirectory, VirtualFileName, WidthPixels, HeightPixels);
return true; //Image Processed
}
else //Raw Image is not in folder, therefore, show "No Image"
{
if (File.Exists(NoImageFile))
{
FromFile(NoImageFile);
return true; //Image Processed
}
else
{
return false; //No Path/Image Found
}
}
}
#endregion
}
}
Bitmap IMG;
byte[] imgData;
System.Drawing.Imaging.ImageFormat imgFormat;
public void SetSize(string InPath, string OutPath, string ImageName, int Width, int Height)
{
string[] fs = Directory.GetFiles(InPath, ImageName);
// string Ffull;
string Fshort;
foreach (string Ffull in fs)
{
FromFile(Ffull);
Fshort = Ffull.Substring(Ffull.LastIndexOf("\\") + 1);
Reduce(int.Parse(Width.ToString(), new System.Globalization.CultureInfo("EN-us")), int.Parse(Height.ToString(), new System.Globalization.CultureInfo("EN-us")), InPath, ImageName);
ToFile(OutPath + Fshort);
}
}
private void Reduce(int Width, int Height, string inpath, string ImageName)
{
IMG = new Bitmap(IMG, new Size(Width, Height));
MemoryStream ms = new MemoryStream();
System.Drawing.Bitmap photo = new System.Drawing.Bitmap(inpath + ImageName);
System.Drawing.Graphics mG = System.Drawing.Graphics.FromImage(IMG);
mG.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
mG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
mG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
mG.DrawImage(photo, 0, 0, Width, Height);
IMG.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
photo.Dispose();
}
private void ToFile(string filename)
{
MemoryStream ms = new MemoryStream();
IMG.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
imgData = new byte[ms.Length];
ms.Position = 0;
ms.Read(imgData, 0, Convert.ToInt32(ms.Length));
FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
fs.Write(imgData, 0, imgData.Length);
fs.Close();
}
private void FromFile(string filename)
{
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
imgData = new byte[fs.Length];
fs.Read(imgData, 0, Convert.ToInt32(fs.Length));
fs.Close();
IMG = (Bitmap)Image.FromStream(new MemoryStream(imgData));
imgFormat = IMG.RawFormat;
}
#endregion
}
}
Step 2 : Compile the above code and copy the Handler.dll from bin directory of this Class Library Project.
Step 3 : Create another web site PictureServer and configure it with IIS.
Step 4 : Copy the following lines at the appropriate place in the web.config of PictureServer Project.
Step 5 : Create following folders at your end.
C:\xlarge
C:\pic\s
C:\pic\m
C:\pic\l
Step 6 : Put some raw .jpg images in xlarge folder.
Step 7 : Copy the Handler.dll from the bin folder of Handler.dll class and paste it in the bin folder of PictureServer project.
Step 8: We also need to map the IIS with .jpg extension
Open the Internet Services Manager tool, right click on Web Site, select Properties, go to Home Directory tab and press Configuration button. This will popup Application Configuration dialog. Click Add button and fill the Executable field with the path to the aspnet_isapi.dll file and fill .jpg in the Extension field. Please ensure that Verify that file exists is unchecked as shown in figure.
,Oh……it is finished…..Now time to test it.
Test
Open the Internet Explorer. Put the following url in the address.
http://localhost/pictureserver/s/1.jpg
Please ensure that 1.jpg image is lying in c:\xlarge folder (raw image).
Result
You will also find processed image in the c:\pic\s folder with proper size.
Repeat the testing for the following urls too.
http://localhost/pictureserver/m/1.jpg
http://localhost/pictureserver/l/1.jpg
The above idea is borrowed heavily from the following resources:
http://www.15seconds.com/Issue/020417.htm
www.c-sharpcorner.com/Code/2003/June/HTTPHandlersForImages.asp
3 comments:
Too much code.. I am lost :|
Quoting:
String[] FilePathArray = app.FilePath.Split('\\', '/');
if (FilePathArray.Length > 2) // need at least /directory/imagename.jpg
{
String FileName = FilePathArray[FilePathArray.Length - 1].ToUpper();
String DirectoryName = FilePathArray[FilePathArray.Length - 2].ToUpper();
//Make sure the file name is at least long enough for X.JPG
if (FileName.Length > 4)
{
if (FileName.Substring(FileName.Length - 4, 4) == ".JPG")
{
I'd suggest using the System.IO methods like Path.GetExtension(), Path.GetFileName(), en Path.GetDirectoryName()!
Hi,
I used the following to read an HTML file and display it in browser. The problem is Images in the html file are not displayed. Any suggestions?
MAK
public void DisplayHtmlFileA()
{
// use this line if local path inside IIS app:
string fullPath = "engSite/Section-I.html";
if (!File.Exists(Server.MapPath(fullPath)))
{
Server.Transfer("Default.aspx");
}
FileStream fs = new FileStream(Server.MapPath(fullPath), FileMode.Open, FileAccess.Read);
BinaryReader binRdr = new BinaryReader(fs);
byte[] content = new byte[fs.Length];
try
{
binRdr.Read(content, 0, content.Length);
DisplayPage(content);
}
catch
{
Server.Transfer("Default.aspx");
}
finally
{
if (binRdr != null)
binRdr.Close();
}
}
private void DisplayPage(byte[] binary)
{
Response.Buffer = false;
Response.ClearHeaders();
Response.ContentType = "text/HTML";
string docname = "Proposal.html";
Response.AddHeader("Content-Disposition", "attachment; filename=" + docname);
//
//Code for streaming the object while writing
const int ChunkSize = 1024;
byte[] buffer = new byte[ChunkSize];
MemoryStream ms = new MemoryStream(binary);
int SizeToWrite = ChunkSize;
for (int i = 0; i < binary.GetUpperBound(0) - 1; i = i + ChunkSize)
{
if (!Response.IsClientConnected) return;
if (i + ChunkSize >= binary.Length) SizeToWrite = binary.Length - i;
byte[] chunk = new byte[SizeToWrite];
ms.Read(chunk, 0, SizeToWrite);
Response.BinaryWrite(chunk);
Response.Flush();
}
Response.Close();
}
Post a Comment