关于在httpHandlers增加了一个,但是URL中包含空格,无法处理

经过测试,如果URL中包含空格,就无法截获请求。

    <httpHandlers>      
      <add verb="*" path="/photo/*.aspx" type="HttpHandler.PhotoHandler, Common"/>
    </httpHandlers>


<!-- BEGIN PhotoHandler -->
      <add key="photopath" value="/style/photos/"/>
      <add key="cachedir" value="40x40,98x98,178X178"/>
      <add key="allow external referrers" value="yes"/>
      <add key="allow referrers" value="yes"/>
      <add key="no access" value="noaccess.jpg"/>
      <add key="no photo" value="nophoto.jpg"/>
      <add key="eboard height" value="125"/>
      <add key="eboard width" value="125"/>
      <add key="watermark minimum width" value="100"/>
      <add key="watermark text position" value="0,1"/>
      <add key="watermark image position" value="1,1"/>
      <add key="watermark transparence" value="0.7"/>
      <add key="watermark type" value="text, image"/>
      <add key="watermark font" value="Verdana"/>
      <add key="watermark color" value="#FFFFFF"/>
      <add key="watermark graphic" value=""/>
      <add key="watermark graphic transparent color" value="white"/>
      <add key="watermark text" value=""/>
      <add key="watermark size" value="14"/>
      <add key="watermark shadow color" value="#000000"/>
      <add key="watermark shadow distance" value="1.5"/>
      <!-- END PhotoHandler -->


using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Configuration;

using Common;
using Common.Config;

namespace HttpHandler
{
    public class PhotoHandler : IHttpHandler
    {
        private HttpResponse response;
        private HttpRequest request;
        private HttpServerUtility server;

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            server = context.Server;
            response = context.Response;
            request = context.Request;

            string fileName = Path.GetFileName(request.Url.AbsolutePath);
            string pattern = @"(\d*)\.([0-9])\.(\d*)\.(\d*)\.((\w|\s|\-)*\.(jpg|gif|bmp))\.aspx";
            Regex re = new Regex(pattern, RegexOptions.IgnoreCase);

            // Check to see if we've found a match
            if (re.IsMatch(fileName))
            {
                int start = 0;
                string s = GetStr(fileName, ref start);
                string t = GetStr(fileName, ref start);
                string w = GetStr(fileName, ref start);
                string h = GetStr(fileName, ref start);
                string n = fileName.Substring(start, fileName.Length - start - 5);
                RequestImage(s, t, w, h, n);
            }
        }

        public static string GetStr(string input, ref int start)
        {
            int index = input.IndexOf('.', start);
            int length = index - start;
            int oldStart = start;
            start = index + 1;
            return input.Substring(oldStart, length);
        }

        private void RequestImage(string strs, string strt, string strw, string strh, string fileName)
        {
            // 分解参数以得到相应的和图片相关的信息
            // thumb=1 => /photos/888/images/, thumb=2 => /photos/888/temp/
            int thumb = 0, width = 0, height = 0;
            Int64 shopId = 0;

            string imagePath = "";

            if (this.IsInt(strs))
            {
                shopId = Int64.Parse(strs);
            }
            if (this.IsInt(strt))
            {
                thumb = int.Parse(strt);
            }
            if (this.IsInt(strw))
            {
                width = int.Parse(strw);
            }
            if (this.IsInt(strh))
            {
                height = int.Parse(strh);
            }

            // 默认取/photos/images/下的图片
            imagePath = strs + "/images/" + fileName;
            // t=2时,取/photos/temp/下的图片
            if (thumb == 2)
            {
                imagePath = strs + "/temp/" + fileName;
            }
            // t=3时,从配置文件中取图片的规定大小
            else if (thumb == 3)
            {
                height = Int32.Parse(Setting("eboard height"));
                width = Int32.Parse(Setting("eboard width"));
            }

            // 检查是否允许被外部引用
            if (Setting("allow external referrers") == "no"
                && request.UrlReferrer != null
                /*&& request.UrlReferrer.Host != request.Url.Host*/)
            {
                imagePath = ShowNoAccessImage();
            }
            // 检查是否允许被内部引用
            if (Setting("allow referrers") == "no"
                && request.UrlReferrer != null
                /*&& request.UrlReferrer.Host == request.Url.Host*/)
            {
                imagePath = ShowNoAccessImage();
            }

            // 获取图片的完整路径
            imagePath = server.MapPath(Setting("photopath") + imagePath);

            ShowImage(strs, imagePath, width, height);
        }

        /// <summary>
        /// 显示不能通过的图片
        /// </summary>
        /// <returns></returns>
        private string ShowNoAccessImage()
        {
            return Setting("no access");
        }

        /// <summary>
        /// 显示处理后的图片
        /// </summary>
        /// <param name="shop"></param>
        /// <param name="image_path"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        private void ShowImage(string shop, string image_path, int width, int height)
        {
            // 获取缓存的图片
            string cachedir = Setting("cachedir").ToLower();
            string str = width.ToString() + "x" + height.ToString();
            string fileName = Path.GetFileName(image_path);
            string strdir = server.MapPath(Setting("photopath")) + shop + "\\" + str;
            // 判断缓存的图片是否超过了7天,如果超过了7天,重新生成,保证图片的定时更新问题。
            string strpath = strdir + "\\" + fileName;
            bool bRemake = true;
            if (File.Exists(strpath))
            {
                FileInfo finfo = new FileInfo(strpath);
                TimeSpan ts = DateTime.Now - finfo.CreationTime;
                if (ts.Days < 7)
                {
                    bRemake = false;
                }
            }
            if (bRemake)
            {
                #region 根据不同的参数缩放

                // Grab Image
                Bitmap image = null;
                try
                {
                    image = (Bitmap)Bitmap.FromFile(image_path);
                }
                catch (Exception e)
                {
                    image_path = server.MapPath(Setting("photopath")) + Setting("no photo");
                    image = (Bitmap)Bitmap.FromFile(image_path);
                }
                Bitmap output = null;

                int ih = 0, iw = 0;
                ih = image.Height;
                iw = image.Width;
                if (height > 0 && width > 0)
                {
                    //if (height / width > ih / iw)
                    if ((float)height / (float)width > (float)ih / (float)iw)
                    {
                        height = (int)((float)ih * width / (float)iw);
                    }
                    else
                    {
                        width = (int)((float)iw * height / (float)ih);
                    }
                }
                else if (height > 0 && width <= 0)
                {
                    width = (int)(image.Width * (float)height / (float)image.Height);
                }
                else if (height <= 0 && width > 0)
                {
                    height = (int)(image.Height * (float)width / (float)image.Width);
                }
                else
                {
                    height = image.Height;
                    width = image.Width;
                }

                output = Resize(image, height, width);

                //Do we watermark it?
                int wmmw = Int32.Parse(Setting("watermark minimum width"));

                if (output.Width >= wmmw)
                {
                    //Add watermark
                    string type = Setting("watermark type");
                    if (type.IndexOf("text") != -1)
                    {
                        string text = Setting("watermark text").Trim();
                        if (!string.IsNullOrEmpty(text))
                            output = TextWaterMark(output);
                    }
                    if (type.IndexOf("image") != -1)
                    {
                        string imgfile = Setting("watermark graphic").Trim();
                        if (!string.IsNullOrEmpty(imgfile))
                            output = ImageWaterMark(output);
                    }
                }

                output.Save(response.OutputStream, ImageType(image_path));

                // 缓存指定大小的图片
                if (cachedir.IndexOf(str) != -1 && image_path.IndexOf(Setting("no photo")) == -1)
                {
                    if (!Directory.Exists(strdir))
                        Directory.CreateDirectory(strdir);
                    output.Save(strdir + "\\" + fileName);
                }

                image.Dispose();
                output.Dispose();

                #endregion

                // WriteLog.WriteError("缩放" + fileName);
            }
            else
            {
                // WriteLog.WriteError("跳转" + str + "/" + fileName);
                response.WriteFile(strdir + "/" + fileName);
            }
        }

        /// <summary>
        /// 设置水印在图片上的位置
        /// </summary>
        /// <param name="image"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private PointF GetPosition(Bitmap image, float width, float height, int type)
        {
            // 原始图片的大小
            float w = image.Width;
            float h = image.Height;

            // 水印偏移位置
            string str = type == 1 ? Setting("watermark text position") : Setting("watermark image position");
            string[] offset = str.Split(',');
            float offsetx = float.Parse(offset[0].Trim());
            float offsety = float.Parse(offset[1].Trim());
            offsetx = offsetx == 1 ? 1 : offsetx % 1;
            offsety = offsety == 1 ? 1 : offsety % 1;
            return new PointF((w - width) * offsetx, (h - height) * offsety);
        }

        #region TextWaterMark(Bitmap image)

        private Bitmap TextWaterMark(Bitmap image)
        {
            Graphics watermark = Graphics.FromImage(image);
            // Set the rendering quality for this Graphics object
            watermark.SmoothingMode = SmoothingMode.AntiAlias;
            int width = image.Width;
            int height = image.Height;

            // 颜色
            Color color = ColorTranslator.FromHtml(Setting("watermark color"));
            // 字体
            string font = Setting("watermark font");
            // 字体大小
            float size = float.Parse(Setting("watermark size"));
            // 水印字符串
            string text = Setting("watermark text");
            // 是否使用阴影
            string shadow = Setting("watermark shadow color");
            // 字体之间的距离
            string distance = Setting("watermark shadow distance");

            //-------------------------------------------------------
            //to maximize the size of the Copyright message we will
            //test multiple Font sizes to determine the largest posible
            //font we can use for the width of the Photograph
            //define an array of point sizes you would like to consider as possiblities
            //-------------------------------------------------------
            int[] sizes = new int[] { 16, 14, 12, 10, 8, 6, 4 };

            Font crFont = null;
            SizeF crSize = new SizeF();

            // 如果字体太大使用合适的字体
            crFont = new Font(font, size, FontStyle.Bold);
            //Measure the Copyright string in this Font
            crSize = watermark.MeasureString(text, crFont);
            if ((ushort)crSize.Width > (ushort)width)
            {
                //Loop through the defined sizes checking the length of the Copyright string
                //If its length in pixles is less then the image width choose this Font size.
                for (int i = 0; i < 7; i++)
                {
                    //set a Font object to Arial (i)pt, Bold
                    crFont = new Font(font, sizes[i], FontStyle.Bold);
                    //Measure the Copyright string in this Font
                    crSize = watermark.MeasureString(text, crFont);

                    if ((ushort)crSize.Width < (ushort)width)
                        break;
                }
            }

            // 文字的高和宽
            PointF pf = GetPosition(image, crSize.Width, crSize.Height, 1);
            pf.X += crSize.Width / 2;

            //Define the text layout by setting the text alignment to centered
            StringFormat StrFormat = new StringFormat();
            StrFormat.Alignment = StringAlignment.Center;

            //define a Brush which is semi trasparent black (Alpha set to 153)
            SolidBrush semiTransBrush2 = new SolidBrush(Color.FromArgb(153, 0, 0, 0));

            //Draw the Copyright string
            watermark.DrawString(text,                 //string of text
                crFont,                                   //font
                semiTransBrush2,                           //Brush
                new PointF(pf.X + 1, pf.Y + 1),  //Position
                StrFormat);

            //define a Brush which is semi trasparent white (Alpha set to 153)
            SolidBrush semiTransBrush = new SolidBrush(Color.FromArgb(153, 255, 255, 255));

            //Draw the Copyright string a second time to create a shadow effect
            //Make sure to move this text 1 pixel to the right and down 1 pixel
            watermark.DrawString(text,                 //string of text
                crFont,                                   //font
                semiTransBrush,                           //Brush
                pf,                                       //Position
                StrFormat);                               //Text alignment
            watermark.Dispose();
            return image;
        }

        #endregion

        #region ImageWaterMark(Bitmap image)

        private Bitmap ImageWaterMark(Bitmap image)
        {
            Graphics watermark = Graphics.FromImage(image);
            // Set the rendering quality for this Graphics object
            watermark.SmoothingMode = SmoothingMode.AntiAlias;

            string wm_image_path = server.MapPath(Setting("photopath")) + Setting("watermark graphic");
            if (File.Exists(wm_image_path))
            {
                Bitmap wm_image = (Bitmap)Bitmap.FromFile(wm_image_path);
                // if the watermark's width is big than the original image's width
                if (image.Width / 2 < wm_image.Width)
                {
                    float w = image.Width / 2;
                    float h = w / wm_image.Width * wm_image.Height;
                    wm_image = Resize(wm_image, (int)h, (int)w);
                }
                string transparent = Setting("watermark graphic transparent color");
                if (transparent != null)
                {
                    Color t_color = ColorTranslator.FromHtml(transparent);
                    wm_image.MakeTransparent(t_color);
                }

                //To achieve a transulcent watermark we will apply (2) color
                //manipulations by defineing a ImageAttributes object and
                //seting (2) of its properties.
                ImageAttributes imageAttributes = new ImageAttributes();

                //The first step in manipulating the watermark image is to replace
                //the background color with one that is trasparent (Alpha=0, R=0, G=0, B=0)
                //to do this we will use a Colormap and use this to define a RemapTable
                ColorMap colorMap = new ColorMap();

                //My watermark was defined with a background of 100% Green this will
                //be the color we search for and replace with transparency
                colorMap.OldColor = Color.FromArgb(255, 0, 255, 0);
                colorMap.NewColor = Color.FromArgb(0, 0, 0, 0);

                ColorMap[] remapTable = { colorMap };

                imageAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap);

                float transparence = float.Parse(Setting("watermark transparence"));

                //The second color manipulation is used to change the opacity of the
                //watermark.  This is done by applying a 5x5 matrix that contains the
                //coordinates for the RGBA space.  By setting the 3rd row and 3rd column
                //to 0.3f we achive a level of opacity
                float[][] colorMatrixElements = {
            new float[] {1.0f,  0.0f,  0.0f,  0.0f, 0.0f},      
            new float[] {0.0f,  1.0f,  0.0f,  0.0f, 0.0f},       
            new float[] {0.0f,  0.0f,  1.0f,  0.0f, 0.0f},       
            new float[] {0.0f,  0.0f,  0.0f,  transparence, 0.0f},       
            new float[] {0.0f,  0.0f,  0.0f,  0.0f, 1.0f}};
                ColorMatrix wmColorMatrix = new ColorMatrix(colorMatrixElements);

                imageAttributes.SetColorMatrix(wmColorMatrix, ColorMatrixFlag.Default,
                    ColorAdjustType.Bitmap);

                PointF pf = GetPosition(image, wm_image.Width, wm_image.Height, 2);

                watermark.DrawImage(wm_image,
                    new Rectangle((int)pf.X, (int)pf.Y, wm_image.Width, wm_image.Height),  //Set the detination Position
                    0,                  // x-coordinate of the portion of the source image to draw.
                    0,                  // y-coordinate of the portion of the source image to draw.
                    wm_image.Width,            // Watermark Width
                    wm_image.Height,      // Watermark Height
                    GraphicsUnit.Pixel, // Unit of measurment
                    imageAttributes);   //ImageAttributes Object
            }

            watermark.Dispose();
            return image;
        }

        #endregion

        #region Common

        /// <summary>
        /// 获得URL传送过来的字符行参数
        /// </summary>
        /// <param name="key">参数的key</param>
        /// <returns></returns>
        private string RequestString(string key)
        {
            if (request.QueryString[key] != null && request.QueryString[key] != string.Empty)
            {
                return request.QueryString[key].Trim();
            }
            else
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 判断是否是整数
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private bool IsInt(string value)
        {
            string pattern = @"^[+-]?\d+$";
            return Regex.IsMatch(value, pattern);
        }

        private Bitmap Resize(Bitmap image, int height, int width)
        {
            Bitmap thumb = new Bitmap(width, height);
            Graphics g_thumb = Graphics.FromImage(thumb);
            g_thumb.Clear(Color.White);
            g_thumb.InterpolationMode = InterpolationMode.HighQualityBicubic;
            // Set the rendering quality for this Graphics object
            g_thumb.SmoothingMode = SmoothingMode.AntiAlias;
            g_thumb.DrawImage(image, 0, 0, width, height);
            g_thumb.Dispose();
            return thumb;
        }

        private string ResponseType(string image_path)
        {
            switch (Path.GetExtension(image_path).ToLower())
            {
                case ".bmp": return "Image/bmp";
                case ".gif": return "Image/gif";
                case ".jpg": return "Image/jpeg";
                case ".png": return "Image/png";
                default: return null;
            }
        }

        private ImageFormat ImageType(string image_path)
        {
            switch (Path.GetExtension(image_path).ToLower())
            {
                case ".bmp": return ImageFormat.Bmp;
                case ".gif": return ImageFormat.Gif;
                case ".jpg": return ImageFormat.Jpeg;
                case ".png": return ImageFormat.Png;
                default: return null;
            }
        }

        private string Setting(string key)
        {
            return ConfigHelper.AppSettings[key].ToString().ToLower();
        }

        #endregion
    }
}

posted @ 2008-04-19 15:44  angushine  阅读(754)  评论(0编辑  收藏  举报