using System;
using System.Configuration;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using EW.EWorkpal.Core.Common.MongoProvider.MongoGridFSRepository.Models;
using EW.EWorkpal.Core.System;
using EW.EWorkpal.Services.FileManagerService.ImageProvider;

namespace EW.EWorkpal.Modules.Picture
{
    public class PictureWebHandler : ServiceBase, IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            HttpResponse response = context.Response;
            HttpRequest request = context.Request;
            #region 客户端缓存
            int clientCacheTime;   //客户端缓存时间(秒)
            string clientCacheSecond = GetAppSetting("ClientCacheSecond", true);
            if (!int.TryParse(clientCacheSecond, out clientCacheTime))
                clientCacheTime = 3600;
            string clearHeadImage = request.Headers["Clear-HeadImage"];
            if (!string.IsNullOrEmpty(clearHeadImage))
            {
                ClearClientCaching(context.Response);
                return;
            }
            string headerModified = request.Headers["If-Modified-Since"];
            if (headerModified != null)
            {
                long nowTicks = DateTime.Now.Ticks;
                long modifiedTick = DateTime.Parse(request.Headers["If-Modified-Since"]).Ticks;
                long ticks = nowTicks - modifiedTick;
                if (TimeSpan.FromTicks(ticks).Seconds < clientCacheTime)
                {
                    response.StatusCode = 304;
                    // 这种方式会产生“此操作要求使用 IIS 集成管线模式。 ”的异常  
                    //Response.Headers.Add("Content-Encoding", "gzip");  
                    // Response.Headers.Add 和 Response.AddHeader 但是在MSDN中明确写出,这些都是为了兼容ASP,在.NET 3.5要求使用下面这种方式。  
                    //这种方式不会出现异常  
                    response.AppendHeader("Content-Encoding", "gzip");
                    response.StatusDescription = "Not Madified";
                    response.End();
                    return;
                }
            }
            #endregion
            string regex = GetAppSetting("UrlRegex");
            string sourceRegex = GetAppSetting("SourceUrlRegex");
            string headRegex = GetAppSetting("HeadImageUrlRegex");
            string comLogoRegex = GetAppSetting("ComLogoUrlRegex");
            string url = request.Url.AbsoluteUri;
            int regexIndex;
            if (Regex.IsMatch(url, headRegex, RegexOptions.IgnoreCase))
                regexIndex = 3;
            else if (Regex.IsMatch(url, comLogoRegex, RegexOptions.IgnoreCase))
                regexIndex = 4;
            else if (Regex.IsMatch(url, regex, RegexOptions.IgnoreCase))
                regexIndex = 1;
            else if (Regex.IsMatch(url, sourceRegex, RegexOptions.IgnoreCase))
                regexIndex = 2;
            else
                regexIndex = 0;
            if (regexIndex == 0)
            {
                Error404(response);
                return;
            }
            #region 用户头像
            if (regexIndex == 3)
            {
                var regResult = Regex.Match(url, @"\d+/\d+").Value;
                var str = regResult.Split('/');
                if (str.Length < 2)
                {
                    Error404(response);
                    return;
                }
                int id, size;
                if (!int.TryParse(str[0], out id))
                {
                    Error404(response);
                    return;
                }
                if (!int.TryParse(str[1], out size))
                {
                    Error404(response);
                    return;
                }
                if (size == 0)
                {
                    size = 50;
                }
                else if (size == 1)
                {
                    size = 80;
                }
                else
                {
                    size = 150;
                }
                var srcPicBytes = GetService<IImageService>().GetHeadImage(id);
                if (srcPicBytes != null)
                {
                    Stream stream = GetHighHeadImage(srcPicBytes, size);
                    long dataToRead = stream.Length;
                    byte[] bytes = ((MemoryStream)stream).GetBuffer();
                    response.Buffer = true;
                    response.ContentType = "image/jpeg";
                    while (dataToRead > 0)
                    {
                        if (response.IsClientConnected)
                        {
                            int length = bytes.Length;
                            byte[] buffer = bytes;
                            response.OutputStream.Write(buffer, 0, length);
                            response.Flush();
                            dataToRead = dataToRead - length;
                        }
                        else
                        {
                            dataToRead = -1;
                        }
                    }
                    SetClientCaching(response, DateTime.Now, clientCacheTime);
                }
                else
                {
                    //if (requesthost != picturehost)//盗链,返回提示图片  
                    ////{
                    ////    context.Response.WriteFile("/Img/linknotice/ImageForbiden.jpg");
                    ////}
                    context.Response.ClearContent();
                    context.Response.WriteFile("/img/headimg/noavatar_" + size + "_" + size + ".jpg");
                    context.Response.ContentType = "image/jpeg";
                    context.Response.End();
                    return;

                }
//                context.Response.ClearContent();
//                context.Response.ContentType = "image/jpeg";
                context.Response.End();
                return;
            }

            #endregion

            #region 企业Logo
            if (regexIndex == 4)
            {
                var regResult = Regex.Match(url, @"ent/\d+").Value;
                var str = regResult.Split('/');
                if (str.Length < 2)
                {
                    Error404(response);
                    return;
                }
                int size;
                if (!int.TryParse(str[1], out size))
                {
                    Error404(response);
                    return;
                }
                if (size == 0)
                {
                    size = 50;
                }
                else if (size == 1)
                {
                    size = 100;
                }
                else
                {
                    size = 150;
                } 
                string fileName = regexIndex == 1 ? Regex.Match(url, regex, RegexOptions.IgnoreCase).Groups[1].Value : Regex.Match(url, sourceRegex, RegexOptions.IgnoreCase).Groups[1].Value;
                MongoFileInfo options;
                var srcPicBytes = GetService<IImageService>().Get(fileName, out options);
                if (srcPicBytes != null)
                {
                    Stream stream = GetHighHeadImage(srcPicBytes, size);
                    long dataToRead = stream.Length;
                    byte[] bytes = ((MemoryStream)stream).GetBuffer();
                    response.Buffer = true;
                    response.ContentType = "image/jpeg";
                    while (dataToRead > 0)
                    {
                        if (response.IsClientConnected)
                        {
                            int length = bytes.Length;
                            byte[] buffer = bytes;
                            response.OutputStream.Write(buffer, 0, length);
                            response.Flush();
                            dataToRead = dataToRead - length;
                        }
                        else
                        {
                            dataToRead = -1;
                        }
                    }
                    SetClientCaching(response, DateTime.Now, clientCacheTime);
                }
                else
                {
                    context.Response.ClearContent();
                    context.Response.WriteFile(string.Format("/img/comlogo/{0}x{0}.jpg",size));
                    context.Response.ContentType = "image/jpeg";
                    context.Response.End();
                    return;

                }
//                context.Response.ClearContent();
//                context.Response.ContentType = "image/jpeg";
                context.Response.End();
                return;
            } 
            #endregion

            #region 读取原图

            if (regexIndex == 1 || regexIndex == 2)
            {
                string fileName = regexIndex == 1 ? Regex.Match(url, regex, RegexOptions.IgnoreCase).Groups[1].Value : Regex.Match(url, sourceRegex, RegexOptions.IgnoreCase).Groups[1].Value;
                MongoFileInfo options;
                var srcPicBytes = GetService<IImageService>().Get(fileName, out options);
                if (srcPicBytes == null || srcPicBytes.Length <= 0)
                {
                    Error404(response);
                    return;
                }
                var srcPicStream = new MemoryStream(srcPicBytes);
                Image srcImage = Image.FromStream(srcPicStream);
                Image destImage = null;
                if (regexIndex == 1)
                {
                    int destWidth = int.Parse(Regex.Match(url, regex, RegexOptions.IgnoreCase).Groups[2].Value);
                    int destHeight = int.Parse(Regex.Match(url, regex, RegexOptions.IgnoreCase).Groups[3].Value);
                    string zoomType = Regex.Match(url, regex, RegexOptions.IgnoreCase).Groups[4].Value;
                    bool zoomCut = zoomType.ToUpper() == "-C";
                    bool zoomFit = zoomType.ToUpper() == "-F";
                    //缩略
                    destImage = ZoomPic.Zoom(srcImage,
                                             new ZoomParam
                                             {
                                                 Width = destWidth,
                                                 Height = destHeight,
                                                 Type =
                                                     zoomCut
                                                         ? EnumZoomType.Cut
                                                         : zoomFit ? EnumZoomType.Fit : EnumZoomType.Cut
                                             });
                }
                else
                {
                    //返回原图
                    destImage = srcImage;
                }
                #region 输出
                Stream stream = new MemoryStream();
                try
                {
                    if (destImage != null) destImage.Save(stream, ImageFormat.Jpeg);
                    long dataToRead = stream.Length;
                    byte[] bytes = ((MemoryStream)stream).GetBuffer();
                    SetClientCaching(response, DateTime.Now, clientCacheTime);
                    response.Buffer = true;
                    response.ContentType = "image/jpeg";
                    while (dataToRead > 0)
                    {
                        if (response.IsClientConnected)
                        {
                            int length = bytes.Length;
                            byte[] buffer = bytes;
                            response.OutputStream.Write(buffer, 0, length);
                            response.Flush();
                            dataToRead = dataToRead - length;
                        }
                        else
                        {
                            dataToRead = -1;
                        }
                    }
                }
                catch (Exception e)
                {
                    ClearClientCaching(response);
                    throw new Exception(e.Message);
                }
                finally
                {
                    srcImage.Dispose();
                    srcPicStream.Dispose();
                    if (destImage != null) destImage.Dispose();
                    stream.Dispose();
                }
                #endregion
            }

            #endregion

        }

        #region private methods

        private static string GetAppSetting(string key, bool allowNull = false)
        {
            if (ConfigurationManager.AppSettings[key] == null)
            {
                if (allowNull)
                    return "";
                throw new ConfigurationErrorsException(string.Format("找不到appSettings配置,配置项{0}", key));
            }
            return ConfigurationManager.AppSettings[key];
        }

        private void SetClientCaching(HttpResponse response, DateTime lastModified, int clientCacheTime)
        {
            response.ContentType = "image/jpeg";
            //将ETag Http标头设置为制定字符串  
            response.Cache.SetETag(lastModified.Ticks.ToString(CultureInfo.InvariantCulture));
            //将Last_Modified Http标头设置为提供的System.DateTime值  
            response.Cache.SetLastModified(lastModified);
            //将Cache-Control 标头设置为System.Web.HttpCacheability值之一  
            response.Cache.SetCacheability(HttpCacheability.Public);
            //基于制定的时间跨度设置Cache-Control: max-age HTTP标头  
            response.Cache.SetMaxAge(new TimeSpan(0, 0, 0, clientCacheTime));
            //将缓存过期从绝对时间设置为可调时间  
            response.Cache.SetSlidingExpiration(true);
        }

        private void ClearClientCaching(HttpResponse response)
        {
            response.Cache.SetExpires(DateTime.Now);
        }

        private MemoryStream GetHeadImage(Byte[] file, int size)
        {
            size = size > 150 ? 150 : size;
            MemoryStream stream = new MemoryStream(file);
            Bitmap bmp = new Bitmap(Image.FromStream(stream));
            Image image = bmp.GetThumbnailImage(size, size, null, IntPtr.Zero);
            MemoryStream ms = new MemoryStream();
            image.Save(ms, ImageFormat.Jpeg);
            return ms;
        }

        private MemoryStream GetHighHeadImage(Byte[] file, int size)
        {
            MemoryStream ms = new MemoryStream();
            Image originalImage = Image.FromStream(new MemoryStream(file));
            //新建一个bmp图片
            Image bitmap = new Bitmap(size, size);
            //新建一个画板
            Graphics g = Graphics.FromImage(bitmap);
            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            //清空画布并以透明背景色填充
            g.Clear(Color.Transparent);
            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new Rectangle(0, 0, size, size), new Rectangle(0, 0, originalImage.Width, originalImage.Height), GraphicsUnit.Pixel);
            try
            {
                //以jpg格式保存缩略图
                bitmap.Save(ms, ImageFormat.Png);
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }
            return ms;
        }

        #endregion

        /// <summary>
        /// 返回404
        /// </summary>
        private static void Error404(HttpResponse response)
        {
            response.StatusCode = 404;
            response.Flush();
            response.End();
        }

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

 

posted on 2015-07-15 18:11  skyEci  阅读(275)  评论(0编辑  收藏  举报