예제 #1
0
        void Pipeline_PreHandleImage(System.Web.IHttpModule sender, System.Web.HttpContext context, Caching.IResponseArgs e)
        {
            string info = e.RewrittenQuerystring["getinfo"];

            if (string.IsNullOrEmpty(info))
            {
                return;
            }

            ResponseArgs ra = e as ResponseArgs;

            e.ResponseHeaders.ContentType = "application/json; charset=utf-8";

            NameValueCollection d = new NameValueCollection();

            ra.ResizeImageToStream = new ResizeImageDelegate(delegate(Stream s) {
                try {
                    using (Stream src = ra.GetSourceImage()) {
                        bool attemptFastMode = src.CanSeek;
                        long orig            = attemptFastMode ? src.Position : 0;
                        bool trySlowMode     = !attemptFastMode;
                        if (attemptFastMode)
                        {
                            try {
                                using (Image i = System.Drawing.Image.FromStream(src, false, false)) {
                                    d["width"]  = i.Width.ToString();
                                    d["height"] = i.Height.ToString();
                                }
                            } catch {
                                trySlowMode = true;
                            }
                        }
                        if (trySlowMode)
                        {
                            if (attemptFastMode)
                            {
                                src.Seek(orig, SeekOrigin.Begin);
                            }
                            using (Bitmap b = c.CurrentImageBuilder.LoadImage(src, new ResizeSettings(ra.RewrittenQuerystring))){
                                d["width"]  = b.Width.ToString();
                                d["height"] = b.Height.ToString();
                            }
                        }
                        SimpleJson(s, d, e.RewrittenQuerystring["jsonp"]);
                    }
                } catch (FileNotFoundException) {
                    d["result"] = "404";
                    SimpleJson(s, d, e.RewrittenQuerystring["jsonp"]);
                }
            });
        }
예제 #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="ra"></param>
        /// <param name="vf"></param>
        protected virtual void HandleRequest(HttpContext context, HttpModuleRequestAssistant ra, IVirtualFile vf)
        {
            if (!ra.CachingIndicated && !ra.ProcessingIndicated)
            {
                ra.ApplyRewrittenPath(); //This is needed for both physical and virtual files; only makes changes if needed.
                if (vf != null)
                {
                    ra.AssignSFH(); //Virtual files are not served in .NET 4.
                }
                return;
            }

            context.Items[conf.ResponseArgsKey] = ""; //We are handling the request

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


            ra.EstimateResponseInfo();

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

            //Add the modified date to the request key, if present.
            var modDate = (vf == null) ? System.IO.File.GetLastWriteTimeUtc(ra.RewrittenMappedPath) :
                          (vf is IVirtualFileWithModifiedDate ? ((IVirtualFileWithModifiedDate)vf).ModifiedDateUTC : DateTime.MinValue);

            e.RequestKey = ra.GenerateRequestCachingKey(modDate);


            var settings = new ResizeSettings(ra.RewrittenInstructions);

            e.RewrittenQuerystring        = settings;
            e.ResponseHeaders.ContentType = ra.EstimatedContentType;
            e.SuggestedExtension          = ra.EstimatedFileExtension;


            //A delegate for accessing the source file
            e.GetSourceImage = new GetSourceImageDelegate(delegate() {
                return((vf != null) ? vf.Open() : File.Open(ra.RewrittenMappedPath, 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 (!ra.ProcessingIndicated)
                    {
                        //Just duplicate the data
                        using (Stream source = e.GetSourceImage())
                            source.CopyToStream(stream); //4KiB buffer
                    }
                    else
                    {
                        ImageJob j;
                        //Process the image
                        if (vf != null)
                        {
                            j = new ImageJob(vf, stream, settings);
                        }
                        else
                        {
                            j = new ImageJob(ra.RewrittenMappedPath, stream, settings); //Use a physical path to bypass virtual file system
                        }
                        conf.GetImageBuilder().Build(j);
                    }
                    ra.FireJobSuccess();
                    //Catch not found exceptions
                } catch (System.IO.FileNotFoundException notFound) {
                    if (notFound.Message.Contains(" assembly "))
                    {
                        throw;                                          //If an assembly is missing, it should be a 500, not a 404
                    }
                    //This will be called later, if at all.
                    ra.FireMissing();
                    throw new ImageMissingException("The specified resource could not be located", "File not found", notFound);
                } catch (System.IO.DirectoryNotFoundException notFound) {
                    ra.FireMissing();
                    throw new ImageMissingException("The specified resource could not be located", "File not found", notFound);
                } catch (Exception ex)
                {
                    ra.FireJobException(ex);
                    throw;
                }
            });


            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); //TODO: Verify that caching systems serves request or transfers to StaticFileHandler
        }
예제 #3
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;
        }