ashx文件和HttpHandler

ASHX与HttpHandler详解
本文介绍了ASHX文件和HttpHandler的基本概念及其应用场景。ASHX文件用于编写WebHandler,简化了HTTP请求处理流程,适用于生成动态内容。文章还探讨了HttpHandler的工作原理,包括IHttpHandler接口的使用和HttpHandler工厂的实现。

ashx文件和HttpHandler

ashx 文件用于写web handler的。.ashx必须包含IsReusable. 如下例所示。}.ashx比.aspx的好处在与不用多一个html 注意了VS2005中Web应用程序项目模板里的Generic Handler 项,发现它是一个.ashx文件,实际上它是一个HttpHandler。利用.ashx文件是一个更好的方法,这个文件类似于.aspx文件,可以通过它来调用HttpHandler类,从而免去了普通.aspx页面的控件解析以及页面处理的过程。然后在同目录下,使用解决方案资源管理器,使用"添加"-->"添加类",在类文件名处输入"TextBuilder.ashx.cs"。使用IE测试,输入这个.ashx的地址即可

.ashx 文件用于写web handler的。其实就是带HTML和C#的混合文件。当然你完全可以用.aspx 的文件后缀。使用.ashx 可以让你专注于编程而不用管相关的WEB技术。.ashx必须包含IsReusable. 如下例所示


<% @ webhandler language="C#" class="AverageHandler" %>

using System;
using System.Web;

public class AverageHandler : IHttpHandler
{
public bool IsReusable
{ get { return true; } }
public void ProcessRequest(HttpContext ctx)
{
ctx.Response.Write("hello");
}
}
.ashx比.aspx的好处在与不用多一个html   
注意了VS2005中Web应用程序项目模板里的Generic Handler 项,发现它是一个.ashx文件,实际上它是一个HttpHandler。后来查了一下.Net SDK文档,发现Asp.Net1.1也支持.ashx,但是没有给出详细内容。

我们都知道,HttpHandler是一个彻底自定义Http请求的方法,它通过web.config来定义Asp.Net运行时来过滤出要自定义的Http请求,发送到定义在web.config的指定类中。

利用.ashx文件是一个更好的方法,这个文件类似于.aspx文件,可以通过它来调用HttpHandler类,从而免去了普通.aspx页面的控件解析以及页面处理的过程。这个文件特别适合于生成动态图片,生成动态文本等内容。

建立方法如下:
首先打开一个Web项目,然后在任意目录下使用VS2003解决方案资源管理器的“添加”-->“添加新项”,在对话框中选择“文本文件”,然后在文件名处输入“TextBuilder.ashx”。

然后在同目录下,使用解决方案资源管理器,使用“添加”-->“添加类”,在类文件名处输入“TextBuilder.ashx.cs”。可以看出,它的文件命名规律与.aspx文件相同。

然后在.cs文件处输入以下代码(名称空间略):
using System.Web
public sealed class TextBuilder : IHttpHandler
{
     public void ProcessRequest(HttpContext context)
     {
         context.Response.ClearContent();
         context.Response.ContentType = "text/plain";
         context.Response.Write("Hello World");
         context.Response.End();
     }

     public bool IsReusable
     {
         get { return true; }
     }
}
然后在“TextBuilder.ashx”文件的第一行处输入上面这个类的调用代码:
<%@ WebHandler language="C#" Class="MyNamespace.TextBuilder" codebehind="TextBuilder.ashx.cs" %> 上面的代码需要注意的是:必须在Class项中输入类的完整名称,即包括名称空间及类名称。

最后保存并编译项目。

使用IE测试,输入这个.ashx的地址即可。

大家可以看出Response类有个OutputStream方法,可以向客户端输出二进制数据流,所以在我的项目中,使用这个方法,在一个.ashx中使用DundasChart控件就可以生成非常好的统计图,用它发送二进制数据,方便快捷,而且不需在web.config内输入任何配置代码。

.ashx文件有个缺点,他处理控件的回发事件非常麻烦,比如说如果用它来生成DataGrid的列表也不是不行,但是处理数据的回发,需要一些.aspx页的功能,只有自己手动处理这些功能。所以,一般使用.ashx,用来输出一些不需要回发处理的项目即可。

---------------------------------------------------------------------

什么是HttpHandler

HttpHandler是一个HTTP请求的真正处理中心,也正是在这个HttpHandler容器中,ASP.NET Framework才真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。

IHttpHandler是什么

IHttpHandler定义了如果要实现一个HTTP请求的处理所必需实现的一些系统约定。HttpHandler与HttpModule不同,一旦定义了自己的HttpHandler类,那么它对系统的HttpHandler的关系将是“覆盖”关系。

IHttpHandler如何处理HTTP请求

当一个HTTP请求经同HttpModule容器传递到HttpHandler容器中时,ASP.NET Framework会调用HttpHandler的ProcessRequest成员方法来对这个HTTP请求进行真正的处理。以一个ASPX页面为例,正是在这里一个ASPX页面才被系统处理解析,并将处理完成的结果继续经由HttpModule传递下去,直至到达客户端。

对于ASPX页面,ASP.NET Framework在默认情况下是交给System.Web.UI.PageHandlerFactory这个HttpHandlerFactory来处理的。所谓一个HttpHandlerFactory,所谓一个HttpHandlerFactory,是指当一个HTTP请求到达这个HttpHandler Factory时,HttpHandlerFactory会提供出一个HttpHandler容器,交由这个HttpHandler容器来处理这个HTTP请求。

一个HTTP请求都是最终交给一个HttpHandler容器中的ProcessRequest方法来处理的。

图1:ProcessRequest方法

一个简单的HttpHandler容器

通过实现IHttpHandler接口可以创建自定义HTTP处理程序,该接口只包含两个方法。通过调用IsReusable,IHttpHandlerFactory可以查询处理程序以确定是否可以使用同一实例为多个请求提供服务。ProcessRequest方法将HttpContext实例用作参数,这使它能够访问Request和Response内部对象。在一个HttpHandler容器中如果需要访问Session,必须实现IRequiresSessionState接口,这只是一个标记接口,没有任何方法。

示例1:

using System;

using System.Collections.Generic;

using System.Text;

using System.Web;

using System.Web.SessionState;

 

namespace MyHandler

{

    ///

    /// 目的:实现一个简单的自定义HttpHandler容器

    /// 作者:文野

    /// 联系:stwyhm@cnblogs.com

    ///

    public class MyFirstHandler : IHttpHandler,IRequiresSessionState

    {

        #region IHttpHandler 成员

 

        public bool IsReusable

        {

            get { return true; }

        }

 

        public void ProcessRequest(HttpContext context)

        {

            context.Response.Write("

Hello HttpHandler

");

 

            context.Session["Test"] = "测试HttpHandler容器中调用Session";

            context.Response.Write(context.Session["Test"]);

        }

 

        #endregion

    }

}

在Web.config中加入如下配置:

<httpHandlers>

     <add verb="*" path="*" type="MyHandler.MyFirstHandler, MyHandler"/>

< span>httpHandlers>

    IHttpHandler工厂

    ASP.NET Framework实际不直接将相关的页面资源HTTP请求定位到一个其内部默认的IHttpHandler容器之上,而定位到了其内部默认的IHttpHandler工厂上。IHttpHandler工厂的作用是对IHttpHandler容器进行调度和管理。

    IHttpHandlerFactory接口包含两个方法。GetHandler返回实现IHttpHandler接口的类的实例,ReleaseHandler使工厂可以重用现有的处理程序实例。

    示例2:

示例2:

using System;

using System.Collections.Generic;

using System.Text;

using System.Web;

 

namespace MyHandler

{

    public class MyHandlerFactory : IHttpHandlerFactory

    {

        #region IHttpHandlerFactory 成员

 

        public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)

        {

            string fname = url.Substring(url.IndexOf('/') + 1);

            while (fname.IndexOf('/') != -1)

                fname = fname.Substring(fname.IndexOf('/') + 1);

            string cname = fname.Substring(0, fname.IndexOf('.'));

            string className = "MyHandler." + cname;

 

            object h = null;

 

            try

            {

                // 采用动态反射机制创建相应的IHttpHandler实现类。

                h = Activator.CreateInstance(Type.GetType(className));

            }

            catch (Exception e)

            {

                throw new HttpException("工厂不能为类型"+cname+"创建实例。",e);

            }

 

            return (IHttpHandler)h;

        }

 

        public void ReleaseHandler(IHttpHandler handler)

        {

           

        }

 

        #endregion

    }

 

    public class Handler1 : IHttpHandler

    {

        #region IHttpHandler 成员

 

        public bool IsReusable

        {

            get { return true; }

        }

 

        public void ProcessRequest(HttpContext context)

        {

            context.Response.Write("

来自Handler1的信息。

");

 

        }

 

        #endregion

    }

 

    public class Handler2 : IHttpHandler

    {

        #region IHttpHandler 成员

 

        public bool IsReusable

        {

            get { return true; }

        }

 

        public void ProcessRequest(HttpContext context)

        {

            context.Response.Write("

来自Handler2的信息。

");

 

        }

 

        #endregion

    }

}

 

<think>首先,用户的问题是:“我想查找使用ashx上传文件时显示进度的方法 请问ashx上传文件并显示进度的实现方法”。用户提到了“ashx”,这是ASP.NET中的一般处理程序(Generic Handler)。 从系统指令中,我需要: - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,如[^1]。 - 回答结构清晰,逐步解决问题。 - 确保回答真实可靠。 用户提供了两个引用: - 引用[1]: 描述了在ASP.NET中使用<form>标签上传文件,并在提交时调用RequestProgress()函数。表单目标设置为"frameFileUpload",enctype为"multipart/form-data"。 - 引用[2]: 讨论了实现无刷新文件上传并显示进度条的原理,使用Html、IHttpHandlerIHttpAsyncHandler。 但这些引用是用户提供的,我需要基于这些内容来构建回答。用户说“上述引用仅供参考”,所以我应该主要参考用户的问题我的知识来回答。 用户的核心需求是:使用ashx(即Generic Handler)上传文件并显示进度条的方法。 在ASP.NET中,显示上传进度通常涉及客户端服务器端交互: 1. 客户端:使用HTML表单或Ajax发送文件。 2. 服务器端:处理文件上传。ashx是IHttpHandler的实现,可以用来处理上传。 3. 进度显示:需要实时获取上传进度。传统方法可能使用隐藏iframe或Ajax轮询服务器获取进度。 从引用[1]来看,它提到了使用<form>的onsubmit事件调用RequestProgress(),并将target设置为一个iframe("frameFileUpload"), 这暗示了使用iframe来处理上传,以避免页面刷新,并在后台处理进度。 引用[2]提到使用IHttpAsyncHandler,因为异步处理更适合长时间操作如文件上传,以便在服务器端跟踪进度。 所以,实现方法的关键点: - 使用异步处理程序(IHttpAsyncHandler)来处理上传,因为它可以报告进度。 - 在客户端使用JavaScriptAjax来轮询服务器获取进度更新。 - 或者,使用隐藏的iframe来提交表单,然后用JavaScript监听进度。 具体步骤: 1. **服务器端(ashx处理程序)**:实现一个异步HttpHandler(IHttpAsyncHandler),在BeginProcessRequest方法中处理文件上传。在过程中保存进度状态(如已上传字节数)。 2. **进度存储**:将进度存储在可以被客户端查询的位置,如Session、Application状态或数据库中。通常使用Session,因为它是用户特定的。 3. **进度报告接口**:创建另一个处理程序或方法,返回当前的进度值(如JSON格式)。 4. **客户端**:使用HTML表单上传文件,target设置为一个隐藏iframe以防止页面刷新。onsubmit事件中启动一个JavaScript函数,该函数定期轮询服务器获取进度,并更新UI。 现在,构建回答结构: - **介绍**:简要解释在ASP.NET中使用ashx实现文件上传进度的方法。 - **步骤**:分步骤描述实现过程。 - 步骤1: 创建异步HttpHandler来处理文件上传。 - 步骤2: 在Handler中实现进度跟踪。 - 步骤3: 创建进度查询接口。 - 步骤4: 客户端HTMLJavaScript实现。 - **代码示例**:提供简单的代码片段(虽然不是必须的,但可以帮助理解)。 - **生成相关问题**:在最后添加相关问题。 确保使用中文回答。 引用标识:由于引用是用户提供的,我应该在相关部分添加[^1][^2]。 例如,提到表单设置时引用[^1],提到异步处理时引用[^2]。 最终回答结构: 1. 解释方法。 2. 详细步骤。 3. 代码片段(可选)。 4. 相关问题。 生成相关问题: - 如何优化上传进度显示? - 使用Session存储进度的优缺点? - 如何实现实时进度而不轮询? </think>以下是针对您的问题——“使用ashx上传文件并显示进度的实现方法”——的详细解答。在ASP.NET中,`ashx`文件是一种通用处理程序(IHttpHandler),用于处理HTTP请求。实现文件上传并显示进度条的核心原理是:服务器端通过异步处理(IHttpAsyncHandler)跟踪上传进度,客户端使用JavaScript轮询或监听进度数据,以实现“无刷新”的用户体验。参考您提供的引用[^1][^2],我将基于ASP.NET的底层实现(非服务器控件)来解释步骤,确保方法真实可靠。整个过程分为服务器端客户端两部分,下面逐步说明。 ### 实现步骤 #### 1. **服务器端:创建异步HttpHandlerashx文件)** 在服务器端,您需要实现一个异步处理程序来上传文件并跟踪进度。关键点是使用`IHttpAsyncHandler`接口代替标准的`IHttpHandler`,因为它能更好地处理长时间运行的进程(如文件上传),并实时更新进度状态。 - **创建ashx文件**:在ASP.NET项目中添加一个通用处理程序(例如`UploadHandler.ashx`)。 - **实现进度跟踪**:在`BeginProcessRequest`方法中处理文件上传,将进度(如已上传字节数)存储在会话(Session)中,以便客户端查询。 - **进度存储**:使用`HttpContext.Current.Session`保存进度值,确保每个用户会话独立。进度数据可以定义为百分比或字节数。 示例代码(C#): ```csharp public class UploadHandler : IHttpAsyncHandler { public bool IsReusable => false; public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { var asyncOperation = new AsyncUploadOperation(context, cb, extraData); asyncOperation.Start(); // 开始异步上传 return asyncOperation; } public void EndProcessRequest(IAsyncResult result) { // 清理资源 } public void ProcessRequest(HttpContext context) { // 标准处理(通常为空) } private class AsyncUploadOperation : IAsyncResult { private HttpContext _context; private AsyncCallback _callback; private object _state; private bool _completed; private long _totalBytes; private long _bytesUploaded; public AsyncUploadOperation(HttpContext context, AsyncCallback callback, object state) { _context = context; _callback = callback; _state = state; _context.Session["UploadProgress"] = 0; // 初始化进度Session } public void Start() { var request = _context.Request; _totalBytes = request.ContentLength; var file = request.Files[0]; // 获取上传的文件 // 模拟异步上传:分块读取文件并更新进度 Task.Run(() => { byte[] buffer = new byte[4096]; using (var stream = file.InputStream) { int bytesRead; while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0) { // 这里可以实际保存文件(例如写入磁盘) Thread.Sleep(10); // 模拟上传延迟 _bytesUploaded += bytesRead; int progress = (int)((_bytesUploaded * 100) / _totalBytes); _context.Session["UploadProgress"] = progress; // 更新Session中的进度 } } _completed = true; _callback?.Invoke(this); // 通知完成 }); } // IAsyncResult 接口实现 public bool IsCompleted => _completed; public WaitHandle AsyncWaitHandle => null; public object AsyncState => _state; public bool CompletedSynchronously => false; } } ``` - **说明**:此代码定义了`IHttpAsyncHandler`的子类,在`Start`方法中模拟文件上传过程。进度值(百分比)存储在Session中(`_context.Session["UploadProgress"]`)。实际使用时,需添加错误处理文件保存逻辑(如`System.IO.File.WriteAllBytes`)。 - **进度查询接口**:创建另一个简单ashx处理程序(如`ProgressHandler.ashx`),返回当前进度(JSON格式),供客户端轮询。 ```csharp public class ProgressHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "application/json"; int progress = context.Session["UploadProgress"] != null ? (int)context.Session["UploadProgress"] : 0; context.Response.Write($"{{\"progress\": {progress}}}"); // 返回JSON进度数据 } public bool IsReusable => false; } ``` - **注意**:Session状态需要在应用程序中启用(在Web.config设置`<sessionState mode="InProc" />`)。引用[^2]提到使用异步处理程序(IHttpAsyncHandler)是实现进度的关键,因为它避免了阻塞线程并支持进度报告[^2]。 #### 2. **客户端:HTML表单JavaScript实现** 客户端负责触发上传并显示进度条。使用HTML表单提交文件,但通过JavaScript隐藏iframe实现“无刷新”。参考引用[^1]中的方法,`<form>`的`target`设置为一个iframe,`onsubmit`事件启动进度轮询。 - **HTML部分**:创建表单一个隐藏的iframe(用于接收服务器响应而不刷新页面)。 ```html <form id="uploadForm" action="UploadHandler.ashx" method="post" enctype="multipart/form-data" target="hiddenFrame"> <input type="file" name="file" id="fileInput" /> <input type="submit" value="上传" /> </form> <iframe id="hiddenFrame" name="hiddenFrame" style="display:none;"></iframe> <div id="progressBar" style="width:100%; background:#eee;"> <div id="progress" style="width:0%; height:20px; background:green;"></div> </div> ``` - **JavaScript部分**:使用`onsubmit`事件启动轮询函数,定期向进度查询接口(ProgressHandler.ashx)发送请求,更新UI。 ```javascript function startProgressPolling() { let progressElement = document.getElementById('progress'); let interval = setInterval(function() { fetch('ProgressHandler.ashx') // 轮询进度接口 .then(response => response.json()) .then(data => { progressElement.style.width = data.progress + '%'; if (data.progress >= 100) { clearInterval(interval); // 上传完成时停止轮询 alert('上传完成!'); } }) .catch(error => console.error('进度获取失败:', error)); }, 500); // 每500毫秒轮询一次 } document.getElementById('uploadForm').onsubmit = startProgressPolling; ``` - **说明**:表单提交时,文件上传到服务器端的`UploadHandler.ashx`,同时JavaScript轮询`ProgressHandler.ashx`获取进度并更新进度条。引用[^1]中提到的`onsubmit`事件iframe目标设置是实现无刷新的核心技巧[^1]。现代实现中,可以使用Fetch API(如上)或XMLHttpRequest,但iframe方法兼容性更好。 ### 关键注意事项 - **性能与可靠性**:此方法在低并发时工作良好,但Session存储可能在高并发下成为瓶颈。优化方案包括使用内存缓存(如Redis)或数据库存储进度。 - **错误处理**:服务器端应添加异常捕获(如文件大小限制),客户端处理网络错误。 - **安全**:确保上传处理程序验证文件类型(如检查MIME类型),防止恶意上传。 - **实际部署**:在真实环境中,考虑使用第三方库(如jQuery插件)简化进度UI,但本方法避免了服务器控件,保持轻量[^2]。 ### 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值