仅当文件不存在时才会触发HttpHandler

时间:2022-08-29 23:01:34

I'm trying to create a HTTP handler to handle all requests to a folder but I only want it to fire if the files requested don't exist (EG: Request comes in for file X, if X exists I'd like to serve the file, otherwise the handler should deal with it).

我正在尝试创建一个HTTP处理程序来处理对文件夹的所有请求,但我只想在请求的文件不存在时触发它(EG:请求来自文件X,如果X存在我想要服务该文件,否则处理程序应该处理它)。

The files will only be static content, not scripts themselves, which I assume makes it a bit easier but I can't seem to find anything that will do the trick... Anyone have any ideas? I assume it can be done since the IIS7 rewrite module can manage it, but I can't see how...

这些文件只是静态内容,而不是脚本本身,我认为它使它更容易但我似乎无法找到任何可以做到这一点的任何东西......任何人都有任何想法?我认为它可以完成,因为IIS7重写模块可以管理它,但我看不出如何...

Edit Just to clarify... the handler is the typical case and it is not an error-handling routine but actually delivering appropriate content. I just want the ability to add new files to the folder either as separate things or as overloads to what the handler would deliver.

编辑只是为了澄清...处理程序是典型的情况,它不是错误处理例程,而是实际提供适当的内容。我只是希望能够将新文件作为单独的东西添加到文件夹中,或者作为处理程序将提供的内容的重载。

3 个解决方案

#1


9  

I've ended up sticking with a handler and instead using the following to solve the problem:

我最终坚持使用处理程序,而是使用以下方法来解决问题:

if (File.Exists(context.Request.PhysicalPath)) context.Response.TransmitFile(context.Request.PhysicalPath);
else { /* Standard handling */ }

Given so many people advocated Modules and catching exceptions I feel I should clarify why I didn't listen:

鉴于有这么多人主张模块和捕捉异常,我觉得我应该澄清为什么我不听:

  1. This is standard program flow, as such I don't like the idea of using an exception to trigger it unless it becomes absolutely necessary.
  2. 这是标准的程序流程,因此我不喜欢使用异常来触发它的想法,除非它变得绝对必要。

  3. This is actually returning content under normal circumstances. The idea of a HttpModule actually handling typical requests rather than just doing some basic shared processing and handling edge-cases seems a bit off. As such I prefer to use a HttpHandler as it is handling the typical requests.
  4. 这实际上是在正常情况下返回内容。 HttpModule实际上处理典型请求而不仅仅是做一些基本的共享处理和处理边缘情况的想法似乎有点过时了。因此,我更喜欢使用HttpHandler,因为它处理典型的请求。

#2


5  

Probably you would want to implement an HttpModule. Otherwise you are fighting with all the other HttpHandlers that are vying for the request.

可能你想要实现一个HttpModule。否则,您正在与争夺请求的所有其他HttpHandler进行斗争。

This should get you started....

这应该让你开始......

You can decide where in the request lifecycle you want to perform your check and react. See this article for some background

您可以决定要在请求生命周期中执行检查和响应的位置。有关背景,请参阅此文章

using System;
using System.IO;
using System.Web;

namespace RequestFilterModuleTest
{
    public class RequestFilterModule : IHttpModule
    {
        #region Implementation of IHttpModule

        /// <summary>
        /// Initializes a module and prepares it to handle requests.
        /// </summary>
        /// <param name="context">
        /// An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods, 
        /// properties, and events common to all application objects within an ASP.NET application 
        /// </param>
        public void Init(HttpApplication context)
        {
            context.BeginRequest += ContextBeginRequest;
        }

        /// <summary>
        /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
        /// </summary>
        public void Dispose()
        {
        }

        private static void ContextBeginRequest(object sender, EventArgs e)
        {
            var context = (HttpApplication) sender;

            // this is the file in question
            string requestPhysicalPath = context.Request.PhysicalPath;

            if (File.Exists(requestPhysicalPath))
            {
                return;
            }

            // file does not exist. do something interesting here.....
        }

        #endregion
    }
}

<?xml version="1.0"?>
<configuration>
    ...............................
    <system.web>
    ...........................
        <httpModules>
            <add name="RequestFilterModule" type="RequestFilterModuleTest.RequestFilterModule"/>
            <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        </httpModules>
    </system.web>
    ...................
</configuration>

#3


0  

If you would prefer to not create an HttpModule, I can think of two hacks:

如果你不想创建一个HttpModule,我可以想到两个hacks:

  1. Use something like mod-rewrite on Apache or II7 rewrite on IIS to allow specific URLs that exist to go through, take anything else and redirect it to your static file. This could be a large list and I would only recommend implementing this hack if you only have a small number of files.
  2. 在IIS上使用mod-rewrite或者在IIS上重写II7,以允许存在的特定URL通过,获取其他任何内容并将其重定向到静态文件。这可能是一个很大的列表,如果你只有少量的文件,我只建议实现这个hack。

  3. Change your URL structure to support a routing script that can check to see if the file exists and return it when appropriate. This approach will likely affect caching, so please use caution.
  4. 更改您的URL结构以支持路由脚本,该脚本可以检查文件是否存在并在适当时返回。这种方法可能会影响缓存,所以请谨慎使用。

Jacob

#1


9  

I've ended up sticking with a handler and instead using the following to solve the problem:

我最终坚持使用处理程序,而是使用以下方法来解决问题:

if (File.Exists(context.Request.PhysicalPath)) context.Response.TransmitFile(context.Request.PhysicalPath);
else { /* Standard handling */ }

Given so many people advocated Modules and catching exceptions I feel I should clarify why I didn't listen:

鉴于有这么多人主张模块和捕捉异常,我觉得我应该澄清为什么我不听:

  1. This is standard program flow, as such I don't like the idea of using an exception to trigger it unless it becomes absolutely necessary.
  2. 这是标准的程序流程,因此我不喜欢使用异常来触发它的想法,除非它变得绝对必要。

  3. This is actually returning content under normal circumstances. The idea of a HttpModule actually handling typical requests rather than just doing some basic shared processing and handling edge-cases seems a bit off. As such I prefer to use a HttpHandler as it is handling the typical requests.
  4. 这实际上是在正常情况下返回内容。 HttpModule实际上处理典型请求而不仅仅是做一些基本的共享处理和处理边缘情况的想法似乎有点过时了。因此,我更喜欢使用HttpHandler,因为它处理典型的请求。

#2


5  

Probably you would want to implement an HttpModule. Otherwise you are fighting with all the other HttpHandlers that are vying for the request.

可能你想要实现一个HttpModule。否则,您正在与争夺请求的所有其他HttpHandler进行斗争。

This should get you started....

这应该让你开始......

You can decide where in the request lifecycle you want to perform your check and react. See this article for some background

您可以决定要在请求生命周期中执行检查和响应的位置。有关背景,请参阅此文章

using System;
using System.IO;
using System.Web;

namespace RequestFilterModuleTest
{
    public class RequestFilterModule : IHttpModule
    {
        #region Implementation of IHttpModule

        /// <summary>
        /// Initializes a module and prepares it to handle requests.
        /// </summary>
        /// <param name="context">
        /// An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods, 
        /// properties, and events common to all application objects within an ASP.NET application 
        /// </param>
        public void Init(HttpApplication context)
        {
            context.BeginRequest += ContextBeginRequest;
        }

        /// <summary>
        /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
        /// </summary>
        public void Dispose()
        {
        }

        private static void ContextBeginRequest(object sender, EventArgs e)
        {
            var context = (HttpApplication) sender;

            // this is the file in question
            string requestPhysicalPath = context.Request.PhysicalPath;

            if (File.Exists(requestPhysicalPath))
            {
                return;
            }

            // file does not exist. do something interesting here.....
        }

        #endregion
    }
}

<?xml version="1.0"?>
<configuration>
    ...............................
    <system.web>
    ...........................
        <httpModules>
            <add name="RequestFilterModule" type="RequestFilterModuleTest.RequestFilterModule"/>
            <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        </httpModules>
    </system.web>
    ...................
</configuration>

#3


0  

If you would prefer to not create an HttpModule, I can think of two hacks:

如果你不想创建一个HttpModule,我可以想到两个hacks:

  1. Use something like mod-rewrite on Apache or II7 rewrite on IIS to allow specific URLs that exist to go through, take anything else and redirect it to your static file. This could be a large list and I would only recommend implementing this hack if you only have a small number of files.
  2. 在IIS上使用mod-rewrite或者在IIS上重写II7,以允许存在的特定URL通过,获取其他任何内容并将其重定向到静态文件。这可能是一个很大的列表,如果你只有少量的文件,我只建议实现这个hack。

  3. Change your URL structure to support a routing script that can check to see if the file exists and return it when appropriate. This approach will likely affect caching, so please use caution.
  4. 更改您的URL结构以支持路由脚本,该脚本可以检查文件是否存在并在适当时返回。这种方法可能会影响缓存,所以请谨慎使用。

Jacob