Skip to content

Instantly share code, notes, and snippets.

@BillKeenan
Created February 16, 2021 17:34
Show Gist options
  • Save BillKeenan/49c890ae6ea64ff77d53cec109d002a5 to your computer and use it in GitHub Desktop.
Save BillKeenan/49c890ae6ea64ff77d53cec109d002a5 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Policy;
using System.ServiceModel.Web;
using System.Text;
using System.Web;
using System.Web.Caching;
using Core.Model;
using Core.Model.impl;
using Core.Repositories.interfaces;
using Core.Utility;
using IOC;
using ServiceInterfaces;
using StructureMap;
namespace PlayService
{
/// <summary>
/// Summary description for ImageHandler
/// </summary>
public class ImageHandler : IHttpHandler
{
private IDatabaseHandler _databaseHandler;
private ILoggerService _loggerService;
private readonly IDropDeckCacheProvider _dropDeckCacheProvider;
public ImageHandler( )
{
Bootstrapper.Bootstrap();
_databaseHandler = ObjectFactory.GetInstance<IDatabaseHandler>();
_loggerService = ObjectFactory.GetInstance<ILoggerService>() ;
_dropDeckCacheProvider = ObjectFactory.GetInstance<IDropDeckCacheProvider>();
}
public void ProcessRequest(HttpContext context)
{
var url = context.Request.RawUrl;
var fi = (FileInfo) HttpRuntime.Cache.Get(url);
if (fi == null || !fi.Exists)
{
var parmas = url.Split(Char.Parse("/"), Char.Parse("?"));
int width = 0;
int height = 0;
if (parmas.Length > 3)
{
var queryParams = QueryHelper.SplitParams(parmas[3]);
//get width)
if (queryParams.ContainsKey("width"))
{
int.TryParse(queryParams["width"], out width);
}
//get width)
if (queryParams.ContainsKey("height"))
{
int.TryParse(queryParams["height"], out height);
}
}
fi = HandleLocalImage(Convert.ToInt32(parmas[2]), context, width, height);
}
if (fi != null )
{
HttpRuntime.Cache.Add(url, fi, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.Normal, null);
ReturnImage(fi, context);
}
else
{
context.Response.StatusCode = 404;
return;
}
}
private FileInfo HandleLocalImage(int id, HttpContext context,int width,int height)
{
var key = String.Format("Image{0}Cache", id);
var resizedkey = String.Format("Image{0}Cache_w:{1}_h:{2}", id,width,height);
FileInfo fi = null;
var sizedFile = (string)HttpRuntime.Cache.Get(resizedkey);
if (!String.IsNullOrEmpty(sizedFile) && File.Exists(sizedFile) )
{
fi = new FileInfo(sizedFile);
}
else
{
var origFile = (string) HttpRuntime.Cache.Get(key);
//get the original filepath
if (String.IsNullOrEmpty(origFile))
{
var filePath = GetImage(id);
if (!String.IsNullOrEmpty(filePath))
{
origFile = String.Format("{0}{1}", ConfigurationManager.AppSettings["ImagePath"], filePath);
HttpRuntime.Cache.Add(key, origFile, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.Normal, null);
}
}
//does the file exist?
if (!String.IsNullOrEmpty(origFile))
{
if (!File.Exists(origFile))
{
_loggerService.Fatal("404:" + origFile);
context.Response.StatusCode = 404;
return null;
}
}
fi = new FileInfo(origFile);
//build the sized url
if (width > 0 || height > 0)
{
var sized = String.Format(@"{0}\{1}", fi.DirectoryName, getFileName(fi.Name, width, height));
//does it exist?
if (!File.Exists(sized) )
{
//create it
fi = ResizeImage(width, height, fi);
}
else
{
fi = new FileInfo(sized);
}
HttpRuntime.Cache.Add(resizedkey, sized, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.Normal, null);
}
}
return fi;
}
public void ReturnImage(FileInfo file, HttpContext context)
{
var etag = Md5Util.GetMd5Hash(file.LastWriteTime.Ticks + file.FullName);
context.Cache[file.FullName] = etag;
switch (file.Extension.ToLower())
{
case ".jpg":
context.Response.ContentType = "image/jpeg";
break;
case ".png":
context.Response.ContentType = "image/png";
break;
case ".gif":
context.Response.ContentType = "image/gif";
break;
default:
throw new ArgumentException("Unknown filetype:" + file.Extension);
}
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetExpires(DateTime.Now.AddDays(1));
context.Response.Cache.SetMaxAge(new TimeSpan(24, 0, 0));
context.Response.Cache.SetETag(etag);
context.Response.WriteFile(file.FullName);
}
private void ProxyFaceBookAvatar(string[] parmas, HttpContext context)
{
if (parmas.Count()<3)
{
context.Response.StatusCode = 500;
return;
}
var id = int.Parse(parmas[3]);
var fileName = String.Format("{0}{1}.jpg", ConfigurationManager.AppSettings["FaceBookAvatar"], id);
var url = String.Format("http://graph.facebook.com/{0}/picture",id);
var fi = new FileInfo(fileName);
if (!fi.Exists)
{
fi = ImageDownloader.DownloadAndSave(url, fileName);
}
ReturnImage(fi,context);
}
public string GetImage(int id)
{
var image = _databaseHandler.Session.Get<Media>(id);
if (image== null || string.IsNullOrEmpty(image.Path))
{
_loggerService.Fatal("could not find media id:" + id);
return null;
}
_loggerService.Info(String.Format("Returning image:{0}",image.Path));
return image.Path;
}
public bool IsReusable
{
get
{
return false;
}
}
private static string getFileName(string name,int width,int height)
{
var sb = new StringBuilder();
sb.Append(width);
sb.Append("_");
sb.Append(height);
sb.Append("_");
sb.Append(name);
return sb.ToString();
}
public static FileInfo ResizeImage(int width, int height,FileInfo fi)
{
if (width == 0 && height == 0)
{
return fi;
}
var newFileName = String.Format(@"{0}\{1}", fi.Directory, getFileName(fi.Name, width, height));
if (File.Exists(newFileName))
{
var newFi = new FileInfo(newFileName);
return newFi;
}
FileInfo finalFI;
//load up the image
using (var image = Image.FromFile(fi.FullName))
{
var scale = (double)width / (double)image.Width;
var jgpEncoder = GetEncoder(ImageFormat.Jpeg);
var myEncoder = System.Drawing.Imaging.Encoder.Quality;
var myEncoderParameters = new EncoderParameters(1);
var myEncoderParameter = new EncoderParameter(myEncoder, 50L);
myEncoderParameters.Param[0] = myEncoderParameter;
using (var fullsizeImage = Image.FromFile(fi.FullName))
{
//get newSize
var newSize = NewSize(fullsizeImage.Size, new Size(width, height));
// Prevent using images internal thumbnail
fullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
fullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
using (var newImage = fullsizeImage.GetThumbnailImage(newSize.Width, newSize.Height, null, IntPtr.Zero))
{
// Clear handle to original file so that we can overwrite it if necessary
// Save resized picture
newImage.Save(newFileName, jgpEncoder, myEncoderParameters);
newImage.Dispose();
finalFI = new FileInfo(newFileName);
}
fullsizeImage.Dispose();
}
}
return finalFI;
}
private static float GetRatio(Size size)
{
return (float)size.Width/size.Height;
}
public static Size NewSize(Size origSize,Size newSize)
{
var finalSize = new Size();
var origRatio = GetRatio(origSize);
var newRatio = GetRatio(newSize);
if (origRatio>newRatio)
{
//width is our base
finalSize.Width = newSize.Width;
finalSize.Height = (int)(finalSize.Width / origRatio);
}else if (origRatio < newRatio)
{
//height is our base
finalSize.Height = newSize.Height;
finalSize.Width = (int)(finalSize.Height * origRatio);
}else
{
//mathching!
finalSize = newSize;
}
return finalSize;
}
private static ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
}
public class QueryHelper
{
public static string BuildQueryParam(Uri theUri, string key, string value)
{
var qVal = theUri.Query;
if (theUri.Query.Length > 0)
{
qVal = theUri.Query.Substring(1, theUri.Query.Length - 1);
}
var vals = QueryHelper.SplitParams(qVal);
var val2 = new Dictionary<string, string>();
foreach (var val in vals)
{
if (val.Key == key)
{
continue;
}
//handle clearing 'all'
if (val.Key.ToLower() == "all" && key.ToLower() != "all")
{
continue;
}
val2.Add(val.Key, val.Value);
}
if (!String.IsNullOrEmpty(value))
{
val2[key] = value;
}
var sb = new StringBuilder();
sb.Append("?");
foreach (var obKey in val2.Keys)
{
if (sb.Length > 1)
{
sb.Append("&");
}
var queryVal = HttpUtility.UrlDecode(val2[obKey]);
sb.Append(String.Format("{0}={1}", obKey, HttpUtility.UrlEncode(queryVal)));
}
return sb.ToString();
}
public static Dictionary<string, string> SplitParams(string uri)
{
var parts = uri.Split(Char.Parse("&"));
var val = new Dictionary<string, string>();
foreach (var part in parts)
{
var item = part.Split(Char.Parse("="));
if (item.Length == 2)
{
val[item[0]] = item[1];
}
}
return val;
}
}
public class ImageDownloader
{
public static FileInfo DownloadAndSave(string imageUrl, string destinationFile)
{
try
{
var client = new WebClient();
using (var stream = client.OpenRead(imageUrl))
{
if (stream != null)
{
using (var bitmap = new Bitmap(stream))
{
stream.Flush();
stream.Close();
stream.Dispose();
bitmap.Save(destinationFile);
bitmap.Dispose();
}
var fi = new FileInfo(destinationFile);
return fi;
}
}
return null;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment