ASP.NET Ashx 裁剪压缩图片

发布于 2017-12-06  224 次阅读


做项目时发现客户有时传的好多海报大图,前台展示轮播几十张会加载很慢,以前只用过php的timthumb,这就自己写了一个asp.net版的使用
调用方式和他类似,
Original:1 or 0是否为返回原图Url
Compress压缩比0-100 100最好
例如:http://yourServer/handlers/thumb.ashx?ImgUrl=/Upload/Poster/20171205/17120511041625.jpg&Width=185&Height=300&Compress=70&Original=
会直接返回图片数据写入到页面内,而且简单做了下缓存处理,就是如果同一个地址同一个宽高的图片,每次处理前会先判断是否已经处理过,如果已经处理过直接找到那个图片返回去就行,省的每次都处理,文件越来越多。

namespace WebApplication.Handlers
{

 /// <summary>
 /// 裁剪压缩图片
 /// </summary>
 public class Thumb : IHttpHandler
 {
 public string SavePath = "/Upload";
 public string ThumbImageDir = "Thumb";
 public void ProcessRequest(HttpContext context)
 {
 string err = string.Empty;
 string original = GetRequestValue("Original"); //返回原图URL 1 0
 string imgUrl = GetRequestValue("ImgUrl");
 string width = GetRequestValue("Width");
 string height = GetRequestValue("Height");
 string compress = GetRequestValue("Compress");//压缩比、1-100
 if (StrEmpty(imgUrl))
 err += " Image url error";
 if (StrEmpty(width))
 err += " Please enter image width";
 if (StrEmpty(height))
 err += " Please enter image height";
 if (!StrEmpty(err))
 {
 context.Response.Write(err);
 context.Response.End();
 }
 //视情况而定,如果是图片完整路径就直接imgUrl就好 此项目中都是相对路径
 imgUrl = "http://" + context.Request.Url.Authority + imgUrl;

 string imgMd5 = GetFileSaveName(imgUrl + "_" + width + "x" + height); //保存的文件名Url的MD5加上宽x高
 string fileExt = Path.GetExtension(imgUrl);

 //返回原图地址
 if (string.Compare(original, "1") == 0)
 {
 context.Response.Write(imgUrl);
 context.Response.End();
 }

 context.Response.ContentType = "image/png";

 string thumbImgPath = SavePath + "/" + ThumbImageDir + "/" + imgMd5 + "_thumb" + fileExt; //压缩后的图片路径
 string strResizeImgPath = HttpContext.Current.Server.MapPath(thumbImgPath);

 string serverThumbImgDir = HttpContext.Current.Server.MapPath(SavePath + "/" + ThumbImageDir);
 if (!Directory.Exists(serverThumbImgDir))
 Directory.CreateDirectory(serverThumbImgDir);

 //如果缩略图已经存在 l
 if (File.Exists(HttpContext.Current.Server.MapPath(thumbImgPath)))
 {
 WriteImg(strResizeImgPath);
 }
 Stream imgSavePath = HttpDownloadFile(imgUrl);

 if (imgSavePath == null)
 {
 err += " Image url error";
 context.Response.Write(err);
 context.Response.End();
 }
 bool flag = false;
 Image thumbImg = Image.FromStream(imgSavePath);
 int imgWidth = thumbImg.Width;
 int imgHeight = thumbImg.Height;
 int maxWidth = Convert.ToInt32(width);
 int maxHeight = Convert.ToInt32(height);
 if (imgWidth > imgHeight) //如果宽度超过高度以宽度为准来调整
 {
 if (imgWidth > maxWidth) //如果图片宽度超过限制
 {
 int toImgWidth = maxWidth; //图片调整后的宽度
 int toImgHeight = imgHeight / (int)(imgWidth / toImgWidth); //图片调整后的高度
 Bitmap img = new Bitmap(thumbImg, int.Parse(toImgWidth.ToString()), int.Parse(toImgHeight.ToString()));
 if (StrEmpty(compress)) img.Save(strResizeImgPath); //保存调整大小后的图片
 else
 Compress(img, strResizeImgPath, Convert.ToInt32(compress)); //压缩
 flag = true;
 }
 }
 else
 {
 if (imgHeight > maxHeight)
 {
 int toImgHeight = maxHeight;
 int toImgWidth = imgWidth / (int)(imgHeight / toImgHeight);
 Bitmap img = new Bitmap(thumbImg, int.Parse(toImgWidth.ToString()), int.Parse(toImgHeight.ToString()));
 if (StrEmpty(compress)) img.Save(strResizeImgPath); //保存调整大小后的图片
 else
 Compress(img, strResizeImgPath, Convert.ToInt32(compress)); //压缩
 flag = true;
 }
 }
 if (flag)
 {
 WriteImg(strResizeImgPath);
 }
 else
 context.Response.Write("Resize Faild");
 }
 public void WriteImg(string imgPath)
{
            var imgStream = new FileStream(imgPath, FileMode.Open);
            byte[] byteImg = new byte[imgStream.Length];
            imgStream.Read(byteImg, 0, byteImg.Length);
            imgStream.Close();
            HttpContext.Current.Response.OutputStream.Write(byteImg, 0, byteImg.Length);
            HttpContext.Current.Response.End();
 }
 /// <summary>
 /// 获取缩略图文件保存的文件名
 /// </summary>
 /// <param name="url">图片URL</param>
 /// <returns></returns>

 public string GetFileSaveName(string url)
 {
 return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(url, "MD5");
 }

 /// <summary>
 /// 获取文件MD5值
 /// </summary>
 /// <param name="fileStream"></param>
 /// <returns></returns>
 public string GetFileMd5(Stream fileStream)
 {
 MD5 md5 = new MD5CryptoServiceProvider();

 byte[] retVal = md5.ComputeHash(fileStream);
 StringBuilder sb = new StringBuilder();
 for (int i = 0; i < retVal.Length; i++)
 {
 sb.Append(retVal[i].ToString("x2"));
 }
 return sb.ToString();
 }
 /// <summary>
 /// 下载URL文件 返回Stream
 /// </summary>
 /// <param name="url">文件URL</param>
 /// <returns></returns>
 public Stream HttpDownloadFile(string url)
 {
 if (!url.Contains("http://") && !url.Contains("https://"))
 {
 url = "http://" + url;
 }
 try
 {
 HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
 myRequest.Timeout = 10000; //超时时间10秒
 HttpWebResponse res = (HttpWebResponse)myRequest.GetResponse();
 if (res.StatusCode == HttpStatusCode.OK)
 {
 Stream responseStream = res.GetResponseStream();
 MemoryStream ms = new MemoryStream();
 byte[] bArr = new byte[1024];
 int size = responseStream.Read(bArr, 0, (int)bArr.Length);
 while (size > 0)
 {
 ms.Write(bArr, 0, size);
 size = responseStream.Read(bArr, 0, (int)bArr.Length);
 }
 return ms;
 }
 else
 return null;
 }
 catch
 {
 return null;
 }
 }

 private ImageCodecInfo GetEncoderInfo(String mimeType)
 {
 int j;
 ImageCodecInfo[] encoders;
 encoders = ImageCodecInfo.GetImageEncoders();
 for (j = 0; j < encoders.Length; ++j)
 {
 if (encoders[j].MimeType == mimeType)
 return encoders[j];
 }
 return null;
 }

 /// <summary>
 /// 图片压缩(降低质量以减小文件的大小)
 /// </summary>
 /// <param name="srcBitmap">传入的Bitmap对象</param>
 /// <param name="destStream">压缩后的Stream对象</param>
 /// <param name="level">压缩等级,0到100,0 最差质量,100 最佳</param>
 public void Compress(Bitmap srcBitmap, Stream destStream, long level)
 {
 System.Drawing.Imaging.ImageCodecInfo myImageCodecInfo;
 System.Drawing.Imaging.Encoder myEncoder;
 EncoderParameter myEncoderParameter;
 EncoderParameters myEncoderParameters;

 // Get an ImageCodecInfo object that represents the JPEG codec.
 myImageCodecInfo = GetEncoderInfo("image/jpeg");

 // Create an Encoder object based on the GUID

 // for the Quality parameter category.
 myEncoder = System.Drawing.Imaging.Encoder.Quality;

 // Create an EncoderParameters object.
 // An EncoderParameters object has an array of EncoderParameter
 // objects. In this case, there is only one

 // EncoderParameter object in the array.
 myEncoderParameters = new EncoderParameters(1);

 // Save the bitmap as a JPEG file with 给定的 quality level
 myEncoderParameter = new EncoderParameter(myEncoder, level);
 myEncoderParameters.Param[0] = myEncoderParameter;
 srcBitmap.Save(destStream, myImageCodecInfo, myEncoderParameters);
 }

 /// <summary>
 /// 图片压缩(降低质量以减小文件的大小)
 /// </summary>
 /// <param name="srcBitMap">传入的Bitmap对象</param>
 /// <param name="destFile">压缩后的图片保存路径</param>
 /// <param name="level">压缩等级,0到100,0 最差质量,100 最佳</param>
 public void Compress(Bitmap srcBitMap, string destFile, long level)
 {
 Stream s = new FileStream(destFile, FileMode.Create);
 Compress(srcBitMap, s, level);
 s.Close();
 }



 public string GetRequestValue(string key)
 {
 try
 {
 return HttpContext.Current.Request[key].ToString();

 }

 catch (global::System.Exception)
 {

 return string.Empty;

 }
 }
 #region 字母随机数
 /// <summary>
 /// 字母随机数
 /// </summary>
 /// <param name="n">生成长度</param>
 /// <returns></returns>
 public static string RandLetter(int n)
 {
 char[] arrChar = new char[]{
 'a','b','d','c','e','f','g','h','i','j','k','l','m','n','p','r','q','s','t','u','v','w','z','y','x',
 '_',
 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','Q','P','R','T','S','V','U','W','X','Y','Z'
 };

 StringBuilder num = new StringBuilder();

 Random rnd = new Random(DateTime.Now.Millisecond);
 for (int i = 0; i < n; i++)
 {
 num.Append(arrChar[rnd.Next(0, arrChar.Length)].ToString());

 }

 return num.ToString();
 }
 #endregion

 /// <summary>
 /// 字符串是否为空
 /// </summary>
 /// <param name="str"></param>
 /// <returns></returns>
 public bool StrEmpty(string str)
 {
 return string.IsNullOrEmpty(str);
 }
 public bool IsReusable
 {
 get
 {
 return false;
 }
 }
 }
}

LoneKing