public void EstimateResponseInfo()
        {
            IEncoder guessedEncoder = null;

            //Only use an encoder to determine extension/mime-type when it's an image extension or when we've set process = always.
            if (ProcessingIndicated)
            {
                guessedEncoder = conf.GetImageBuilder().EncoderProvider.GetEncoder(new ResizeSettings(this.RewrittenInstructions), this.RewrittenVirtualPath);
                if (guessedEncoder == null)
                {
                    throw new ImageProcessingException("Image Resizer: No image encoder was found for the request.");
                }
            }

            //Determine the file extension for the caching system to use if we aren't processing the image
            //Use the existing one if is an image extension. If not, use "unknown".
            // We don't want to suggest writing .exe or .aspx files to the cache!
            string fallbackExtension = PathUtils.GetFullExtension(RewrittenVirtualPath).TrimStart('.');

            if (!conf.IsAcceptedImageType(RewrittenVirtualPath))
            {
                fallbackExtension = "unknown";
            }

            //Determine the mime-type if we aren't processing the image.
            string fallbackContentType = "application/octet-stream";

            //Support JPEG, PNG, GIF, BMP, TIFF mime-types. Otherwise use "application/octet-stream".
            //We can't set it to null - it will default to text/html
            System.Drawing.Imaging.ImageFormat recognizedExtension = DefaultEncoder.GetImageFormatFromExtension(fallbackExtension);
            if (recognizedExtension != null)
            {
                fallbackContentType = DefaultEncoder.GetContentTypeFromImageFormat(recognizedExtension);
            }


            EstimatedContentType   = ProcessingIndicated ? guessedEncoder.MimeType : fallbackContentType;
            EstimatedFileExtension = ProcessingIndicated ? guessedEncoder.Extension : fallbackExtension;

            Performance.GlobalPerf.Singleton.IncrementCounter("module_response_ext_" + EstimatedFileExtension);
        }
Exemple #2
0
        /// <summary>
        /// Generates the resized image to disk (if needed), then rewrites the request to that location.
        /// Perform 404 checking before calling this method. Assumes file exists.
        /// Called during PostAuthorizeRequest
        /// </summary>
        /// <param name="context"></param>
        /// <param name="virtualPath"></param>
        /// <param name="queryString"></param>
        /// <param name="vf"></param>
        protected virtual void HandleRequest(HttpContext context, string virtualPath, NameValueCollection queryString, IVirtualFile vf)
        {
            Stopwatch s = new Stopwatch();

            s.Start();


            ResizeSettings settings = new ResizeSettings(queryString);

            bool isCaching    = settings.Cache == ServerCacheMode.Always;
            bool isProcessing = settings.Process == ProcessWhen.Always;

            //By default, we process it if is both (a) a recognized image extension, and (b) has a resizing directive (not just 'cache').
            if (settings.Process == ProcessWhen.Default)
            {
                //Check for resize directive by removing ('non-resizing' items from the current querystring)
                NameValueCollection copy = new NameValueCollection(queryString);
                copy.Remove("cache"); copy.Remove("process"); copy.Remove("useresizingpipeline"); copy.Remove("404");
                copy.Remove("404.filterMode"); copy.Remove("404.except");
                //If the 'copy' still has directives, and it's an image request, then let's process it.
                isProcessing = conf.IsAcceptedImageType(virtualPath) && conf.HasPipelineDirective(copy);
            }

            //By default, we only cache it if we're processing it.
            if (settings.Cache == ServerCacheMode.Default && isProcessing)
            {
                isCaching = true;
            }

            //Resolve the 'cache' setting to 'no' unless we want it cache.
            if (!isCaching)
            {
                settings.Cache = ServerCacheMode.No;
            }


            //If we are neither processing nor caching, don't do anything more with the request
            if (!isProcessing && !isCaching)
            {
                return;
            }
            context.Items[conf.ResponseArgsKey] = ""; //We are handling the requests

            //Communicate to the MVC plugin this request should not be affected by the UrlRoutingModule.
            context.Items[conf.StopRoutingKey] = true;

            //Find out if we have a modified date that we can work with
            bool     hasModifiedDate = (vf == null) || vf is IVirtualFileWithModifiedDate;
            DateTime modDate         = DateTime.MinValue;

            if (hasModifiedDate && vf != null)
            {
                modDate = ((IVirtualFileWithModifiedDate)vf).ModifiedDateUTC;
                if (modDate == DateTime.MinValue || modDate == DateTime.MaxValue)
                {
                    hasModifiedDate = false; //Skip modified date checking if the file has no modified date
                }
            }


            IEncoder guessedEncoder = null;

            //Only use an encoder to determine extension/mime-type when it's an image extension or when we've set process = always.
            if (isProcessing)
            {
                guessedEncoder = conf.GetImageBuilder().EncoderProvider.GetEncoder(settings, virtualPath);
                if (guessedEncoder == null)
                {
                    throw new ImageProcessingException("Image Resizer: No image encoder was found for the request.");
                }
            }

            //Determine the file extenson for the caching system to use if we aren't processing the image
            //Use the exsiting one if is an image extension. If not, use "unknown".
            // We don't want to suggest writing .exe or .aspx files to the cache!
            string fallbackExtension = PathUtils.GetFullExtension(virtualPath).TrimStart('.');

            if (!conf.IsAcceptedImageType(virtualPath))
            {
                fallbackExtension = "unknown";
            }

            //Determine the mime-type if we aren't processing the image.
            string fallbackContentType = "application/octet-stream";

            //Support jpeg, png, gif, bmp, tiff mime-types. Otherwise use "application/octet-stream".
            //We can't set it to null - it will default to text/html
            System.Drawing.Imaging.ImageFormat recognizedExtension = DefaultEncoder.GetImageFormatFromExtension(fallbackExtension);
            if (recognizedExtension != null)
            {
                fallbackContentType = DefaultEncoder.GetContentTypeFromImageFormat(recognizedExtension);
            }


            //Build CacheEventArgs
            ResponseArgs e = new ResponseArgs();

            e.RequestKey                  = virtualPath + PathUtils.BuildQueryString(queryString);
            e.RewrittenQuerystring        = settings;
            e.ResponseHeaders.ContentType = isProcessing ? guessedEncoder.MimeType : fallbackContentType;
            e.SuggestedExtension          = isProcessing ? guessedEncoder.Extension : fallbackExtension;
            e.HasModifiedDate             = hasModifiedDate;
            //Add delegate for retrieving the modified date of the source file.
            e.GetModifiedDateUTC = new ModifiedDateDelegate(delegate() {
                if (vf == null)
                {
                    return(System.IO.File.GetLastWriteTimeUtc(HostingEnvironment.MapPath(virtualPath)));
                }
                else if (hasModifiedDate)
                {
                    return(modDate);
                }
                else
                {
                    return(DateTime.MinValue); //Won't be called, no modified date available.
                }
            });

            //A delegate for accessing the source file
            e.GetSourceImage = new GetSourceImageDelegate(delegate() {
                return((vf != null) ? vf.Open() : File.Open(HostingEnvironment.MapPath(virtualPath), FileMode.Open, FileAccess.Read, FileShare.Read));
            });

            //Add delegate for writing the data stream
            e.ResizeImageToStream = new ResizeImageDelegate(delegate(System.IO.Stream stream) {
                //This runs on a cache miss or cache invalid. This delegate is preventing from running in more
                //than one thread at a time for the specified cache key
                try {
                    if (!isProcessing)
                    {
                        //Just duplicate the data
                        using (Stream source = e.GetSourceImage())
                            StreamExtensions.CopyToStream(source, stream); //4KiB buffer
                    }
                    else
                    {
                        //Process the image
                        if (vf != null)
                        {
                            conf.GetImageBuilder().Build(vf, stream, settings);
                        }
                        else
                        {
                            conf.GetImageBuilder().Build(HostingEnvironment.MapPath(virtualPath), stream, settings); //Use a physical path to bypass virtual file system
                        }
                    }

                    //Catch not found exceptions
                } catch (System.IO.FileNotFoundException notFound) {
                    //This will be called later, if at all.
                    FileMissing(context, virtualPath, queryString);
                    throw new ImageMissingException("The specified resource could not be located", "File not found", notFound);
                } catch (System.IO.DirectoryNotFoundException notFound) {
                    FileMissing(context, virtualPath, queryString);
                    throw new ImageMissingException("The specified resource could not be located", "File not found", notFound);
                }
            });


            context.Items[conf.ResponseArgsKey] = e; //store in context items

            //Fire events (for client-side caching plugins)
            conf.FirePreHandleImage(this, context, e);

            //Pass the rest of the work off to the caching module. It will handle rewriting/redirecting and everything.
            //We handle request headers based on what is found in context.Items
            ICache cache = conf.GetCacheProvider().GetCachingSystem(context, e);

            //Verify we have a caching system
            if (cache == null)
            {
                throw new ImageProcessingException("Image Resizer: No caching plugin was found for the request");
            }

            cache.Process(context, e);



            s.Stop();
            context.Items["ResizingTime"] = s.ElapsedMilliseconds;
        }