/// <summary> /// The entry point of the handler. Reads settings and request and processes the image or retrieves it from cache /// </summary> /// <param name="context">The context in which the request is done</param> public void ProcessRequest(HttpContext context) { try { //Store the context object for other procedures _context = context; //Get the format and if only format are alowed and one is not given we can stop here. Also scheck if the format actually exists in the settings _format = (_context.Request["format"] ?? string.Empty).ToLower(); if ((string.IsNullOrEmpty(_format) && Settings.FormatsOnly) || (!string.IsNullOrEmpty(_format) && !Settings.Formats.Any(f => f.Key.ToLower() == _format))) { WriteNotFoundResponse(); return; } //resolve the requested file from the servekmage request. (Supports old style serveimage.ashx and new style /image.*) if (_context.Request.Url.AbsolutePath.StartsWith("/serveimage.ashx")) { _requestedFile = _context.Request["path"]; } else { _requestedFile = _context.Request.Url.AbsolutePath.Substring(Settings.PathPrefix.Length); //new } //decode the requested file _requestedFile = HttpUtility.UrlDecode(_requestedFile); //return 404 if the requested file is null or empty if (string.IsNullOrEmpty(_requestedFile)) { WriteNotFoundResponse(); return; } //Resolve the requested category or use the default _category = (_context.Request["cat"] ?? Settings.DefaultCategory).ToLower(); //if a category was given and valid, we add the prefix belonging to the cateogry to the requested file //otherwise If no category could be determined: return a 404 if (Settings.Categories.ContainsKey(_category)) { var prefix = Settings.Categories[_category]; if (!_requestedFile.StartsWith(prefix)) { _requestedFile = prefix + _requestedFile; } } else { WriteNotFoundResponse(); return; } //Resolve the mimetype of the original file and set the contenttype to default to text/html for now. var mimeType = Web.GetMimeType(_requestedFile).ToLower(); _context.Response.ContentType = "text/html"; //Check if the cachepath exists Settings.CheckCachePath(context); //If the requested file is not a local image we return the file as download (e.g. a document) if (!Settings.Categories[_category].StartsWith("http") && !mimeType.StartsWith("image")) { _cacheFile = _context.Server.MapPath(_requestedFile); _cacheFileInfo = new FileInfo(_cacheFile); _serveAsDownload = true; ServeCacheFile(); //and so we can stop here return; } //Fetching more request params _enableCache = bool.Parse(_context.Request["cache"] ?? "true"); _retina = bool.Parse(_context.Request["retina"] ?? "false"); _sizeFactor = _retina ? 2 : 1; _quality = int.Parse(_context.Request["q"] ?? Settings.Quality.ToString()); //Resolve the image manipulation params using the format or the values from the querystring. var format = new NameValueCollection(); if (Settings.Formats.ContainsKey(_format)) { format = Settings.Formats[_format]; } _actions = (format["action"] ?? _context.Request["action"] ?? string.Empty).Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); _serveAsDownload = bool.Parse(format["download"] ?? _context.Request["download"] ?? "false"); _constrainProportions = bool.Parse(format["constrain"] ?? _context.Request["constrain"] ?? "true"); _noUpSizing = bool.Parse(format["noupsizing"] ?? _context.Request["noupsizing"] ?? "false"); _cX = int.Parse(format["cx"] ?? _context.Request["cx"] ?? "0") * _sizeFactor; _cY = int.Parse(format["cy"] ?? _context.Request["cy"] ?? "0") * _sizeFactor; _cW = int.Parse(format["cw"] ?? _context.Request["cw"] ?? "0") * _sizeFactor; _cH = int.Parse(format["ch"] ?? _context.Request["ch"] ?? "0") * _sizeFactor; _rW = int.Parse(format["rw"] ?? _context.Request["rw"] ?? "0") * _sizeFactor; _rH = int.Parse(format["rh"] ?? _context.Request["rh"] ?? "0") * _sizeFactor; _fW = int.Parse(format["fw"] ?? _context.Request["fw"] ?? "0") * _sizeFactor; _fH = int.Parse(format["fh"] ?? _context.Request["fh"] ?? "0") * _sizeFactor; _bW = int.Parse(format["bw"] ?? _context.Request["bw"] ?? "0") * _sizeFactor; _bH = int.Parse(format["bh"] ?? _context.Request["bh"] ?? "0") * _sizeFactor; _mW = int.Parse(format["mw"] ?? _context.Request["mw"] ?? "0") * _sizeFactor; _mH = int.Parse(format["mh"] ?? _context.Request["mh"] ?? "0") * _sizeFactor; _bColor = _context.Request[format["bcolor"] ?? "bcolor"] ?? "ffffff"; //Check if it is an external file _isExternalFile = (_requestedFile.StartsWith("http")); //If not external: get the local file and run some checks if (!_isExternalFile) { if (MediaProvider != null) { var width = (_rW > 0 ? _rW : (_fW > 0 ? _fW : 0)) * (!_retina && Settings.AlwaysUseRetinaAsSource ? 2 : 1); var height = (_rH > 0 ? _rH : (_fH > 0 ? _fH : 0)) * (!_retina && Settings.AlwaysUseRetinaAsSource ? 2 : 1); _mediaFile = MediaProvider(_requestedFile, width, height); } else { _mediaFile = _context.Server.MapPath(_requestedFile); } if (string.IsNullOrEmpty(_mediaFile) || !File.Exists(_mediaFile)) { WriteNotFoundResponse(); return; } _mediaFileInfo = new FileInfo(_mediaFile); } //Convert to jpg (or png if cutout is used) UNLESS overruled by config if (!_isExternalFile || new Uri(_requestedFile, UriKind.RelativeOrAbsolute).IsFile) { var ext = Path.GetExtension(_requestedFile); if (_actions.Contains("cutout") && ext != ".png") { _convertTo = System.Drawing.Imaging.ImageFormat.Png; } else if (ext != ".jpg" && ext != ".jpeg" && !Settings.NoConversion) { _convertTo = System.Drawing.Imaging.ImageFormat.Jpeg; } } //Determine the cachefile _cacheFile = GetCacheFile(); if (_enableCache) { // Is this request cached on the client? if (CheckHttpCache()) { return; } // Do we have the requested file in cache? //media = GetFromCache(); if (CheckDiskCache()) { return; } } // Not in cache it is so loading media file ImageTransformer media; if (_isExternalFile) { media = new ImageTransformer(_requestedFile, _quality); } else { media = new ImageTransformer(_mediaFile, _quality); } //Convert if needed if (_convertTo != null) { media.ConvertToImageFormat(_convertTo); } // Executing actions // Maximum amount of actions is 5, to prevent memory issues if (_actions != null && _actions.Length > 0 && _actions.Length <= 5) { foreach (String action in _actions) { switch (action) { case "resize": media.Resize(new System.Drawing.Size(_rW, _rH), _constrainProportions, _noUpSizing, _mW, _mH); break; case "crop": media.Crop(new System.Drawing.Rectangle(new System.Drawing.Point(_cX, _cY), new System.Drawing.Size(_cW, _cH))); break; case "fit": media.Fit(new System.Drawing.Size(_fW, _fH), _noUpSizing, _mW, _mH); break; case "box": System.Drawing.Color bgColor; if (_bColor == "transparent") bgColor = System.Drawing.Color.Transparent; else bgColor = System.Drawing.ColorTranslator.FromHtml("#" + _bColor); media.Box(new System.Drawing.Size(_bW, _bH), bgColor, _noUpSizing, _mW, _mH); break; case "grayscale": media.Grayscale(); break; case "sepia": media.Sepia(); break; } } } // Cache it! ToCache(media); media.Dispose(); // Serve it! ServeCacheFile(); } catch (System.IO.FileNotFoundException ex) { WriteNotFoundResponse(); return; } }
private void ToCache(ImageTransformer media) { // Directory checking if (!System.IO.Directory.Exists(Settings.CachePath)) System.IO.Directory.CreateDirectory(Settings.CachePath); media.Save(_cacheFile); _cacheFileInfo = new FileInfo(_cacheFile); }