posted on
December 31, 2007
很多朋友可能都讨论过ASP.NET中生成HTML的方法了,有按照模板用IO方法写文件
有在404错误页面内生成HTML的,有在Render内保存页面输出到HTML文件的。
今天我发一个配合Url重写利用HttpHander手工编译.aspx页面方法。
HTML文件的方法,可按需、“定时”的生成,以减轻数据库的访问。
声明:下面的文字是本文不可缺少的部分,转载请保留,谢谢!
////////////////////////////////////////////////////
作者:武眉博<活靶子.NET>
同时首发于:
落伍者 && 博客园
开发者学院 && .Net男孩社区
知识点:UrlRewrite、 IHttpModule、 IHttpHander 的编写
效果:
http://www.devedu.com/Doc/DotNet/AspNet/default.2.aspx
http://www.devedu.com/Doc/DotNet/AspNet/default.2.html
思路:
1 挂载“.aspx"的请求到自定义的Httphander内
2 配置URL重写规则
3 访问某.aspx文件时,在HttpHander内 根据配置确定是否应该生成
接着...
if(需要生成)
{
if(若已经生成html文件 )
{
if(文件并未过期)
{
则直接定向(Server.Transfer())。
}
else
{
删除HTML文件;
重新编译.aspx(Page内数据库操作等等)
生成HTML文件;
}
}
else if(尚未生成文件)
{
生成Html。
}
}
else
{
则编译.aspx文件
}
另:建议阅读一下dudu的blog中关于asp.net页面编译的讨论
http://www.cnblogs.com/dudu/archive/2006/03/07/345107.html
http://www.cnblogs.com/dudu/archive/2006/03/07/344351.html
部分代码
C#代码
- public void ProcessRequest(HttpContext context)
- {
- string rawUrl = context.Request.RawUrl;
- string requestPath = context.Request.Path;
- string applicationPath = context.Request.ApplicationPath;
- Url urlItem = null;
-
-
-
- if (context.Items["ToStaticUrlItem"] == null)
- {
- if (!File.Exists(context.Request.PhysicalPath))
- {
- throw new HttpException(404, "您访问的页面没有找到。");
- }
-
-
-
- IHttpHandler hander = BuildManager.CreateInstanceFromVirtualPath(requestPath, typeof(Page)) as IHttpHandler;
- hander.ProcessRequest(context);
-
- return;
- }
-
- string filePath;
-
- urlItem = (Url)context.Items["ToStaticUrlItem"];
-
- Regex regex = new Regex(
- Globals.ApplicationPath + urlItem.LookFor,
- RegexOptions.CultureInvariant | RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
-
- string requestFile = regex.Replace(rawUrl, Globals.ApplicationPath + urlItem.WriteTo.Replace("^", "&"));
-
- if (requestFile.IndexOf("?") > 0)
- {
- filePath = requestFile.Substring(0, requestFile.IndexOf("?"));
- }
- else
- {
- filePath = requestFile;
- }
-
- string inputFile = context.Request.PhysicalApplicationPath + filePath;
- string path = context.Request.PhysicalApplicationPath + rawUrl.ToLower().Replace(".aspx", ".html");
- if (applicationPath != "/")
- {
- inputFile = inputFile.Replace(applicationPath + "/", @"\");
- path = path.Replace(applicationPath + "/", "").Replace("/", @"\");
- }
- else
- {
- path = path.Replace("/", @"\");
- }
-
- if (!urlItem.EnabledToStatic)
- {
- // asp.net 1.1 采用下面方法编译页面
- //PageParser.GetCompiledPageInstance( filePath , inputFile , context ).ProcessRequest( context );
- IHttpHandler hander = BuildManager.CreateInstanceFromVirtualPath(filePath, typeof(Page)) as IHttpHandler;
- hander.ProcessRequest(context);
-
- return;
- }
-
- if (!File.Exists(path))
- {
- // asp.net 1.1 采用下面方法编译页面
- //PageParser.GetCompiledPageInstance( filePath , inputFile , context ).ProcessRequest( context );
- IHttpHandler hander = BuildManager.CreateInstanceFromVirtualPath(filePath, typeof(Page)) as IHttpHandler;
- hander.ProcessRequest(context);
- context.Response.Filter = new AspxBoy.BuildHtmlDemo.ToHtmlFilter(context.Response.Filter, path);
-
- return;
- }
-
- if (urlItem.Minutes == Int32.MaxValue)
- {
- context.Server.Transfer(rawUrl.ToLower().Replace(".aspx", ".html"));
- }
- else
- {
- FileInfo fileInfo = new FileInfo(path);
- if (fileInfo.LastWriteTime.AddMinutes((double)urlItem.Minutes) < DateTime.Now)
- {
- fileInfo.Delete();
-
- // asp.net 1.1 采用下面方法编译页面
- //PageParser.GetCompiledPageInstance( filePath , inputFile , context ).ProcessRequest( context );
- IHttpHandler hander = BuildManager.CreateInstanceFromVirtualPath(filePath, typeof(Page)) as IHttpHandler;
- hander.ProcessRequest(context);
- context.Response.Filter = new AspxBoy.BuildHtmlDemo.ToHtmlFilter(context.Response.Filter, path);
- }
- else
- {
- context.Server.Transfer(rawUrl.ToLower().Replace(".aspx", ".html"));
- }
- return;
- }
- }
示例项目下载:http://www.cnblogs.com/Files/huobazi/BuildHtmlDemo.rar
posted on
November 2, 2007
其他废话不多说了,代码中都有注释。
如果您熟悉Fckeditor的插件工作流程,请继续向下阅读,另请不要留言要我直接提供下载,下面的代码已经可以完整调试了。
E:\IISROOT\FckTest\FckTest\fckeditor\editor\plugins\remoteimagerubber\remoteimagerubber.aspx
1 <%--
2 使用单页模型(非代码后置),是为了便于此插件部署,
3 不需编译成dll,只需拷贝remoteimagerubber.aspx 和 fckplugin.js 到plugn目录,
4 并配置一下fckconfig.js及相应的语言包,就可以使用了。
5 --%>
6
7 <%@ Page Language="C#" %>
8
9 <%@ Import Namespace="System.Net" %>
10 <%--
11 实现ICallbackEventHandler接口以提供客户端回调功能。
12 --%>
13 <%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>
14
15 <script runat="server">
16
17 /// <summary>
18 /// 此处配置远程文件保存目录
19 /// </summary>
20 private static readonly string savePath = "~/Uploads/";
21
22 /// <summary>
23 /// 此处配置允许下载的文件扩展名
24 /// <remarks>
25 /// 暂未考虑使用动态网页输出的图片如:http://site/image.aspx?uid=00001 这样的URI;
26 /// 若要实现此功能可读取流并判断ContentType,将流另存为相应文件格式即可。
27 /// </remarks>
28 /// </summary>
29 private static readonly string[ ] allowImageExtension = new string[ ] { ".jpg" , ".png" , ".gif" };
30
31 /// <summary>
32 /// 此处配置本地(网站)主机名
33 /// </summary>
34 private static readonly string[ ] localhost = new string[ ] { "localhost" , "www.devedu.com" };
35
36 private string localImageSrc = string.Empty;
37
38 private void Page_Load( object obj , EventArgs args )
39 {
40 if ( !Page.IsPostBack )
41 {
42 ClientScriptManager csm = Page.ClientScript;
43
44 string scripCallServerDownLoad = csm.GetCallbackEventReference( this , "args" , "__ReceiveServerData" , "context" );
45 string callbackScriptDwonLoad = "function __CallServerDownLoad(args , context) {" + scripCallServerDownLoad + "; }";
46 if ( !csm.IsClientScriptBlockRegistered( "__CallServerDownLoad" ) )
47 {
48 csm.RegisterClientScriptBlock( this.GetType( ) , "__CallServerDownLoad" , callbackScriptDwonLoad , true );
49 }
50 }
51 }
52
53 #region ICallbackEventHandler 成员
54
55 /// <summary>
56 /// 返回数据
57 /// </summary>
58 /// <remarks>如果处理过程中出现错误,则仍然返回远程路径</remarks>
59 /// <returns>服务器端处理后的本地图片路径</returns>
60 public string GetCallbackResult( )
61 {
62 return localImageSrc;
63
64 }
65
66 /// <summary>
67 /// 处理回调事件
68 /// </summary>
69 /// <param name="eventArgument">一个字符串,表示要传递到事件处理程序的事件参数</param>
70 public void RaiseCallbackEvent( string eventArgument )
71 {
72
73 string remoteImageSrc = eventArgument;
74
75 string fileName = remoteImageSrc.Substring( remoteImageSrc.LastIndexOf( "/" ) + 1 );
76 string ext = System.IO.Path.GetExtension( fileName );
77
78 if ( !IsAllowedDownloadFile( ext ) )
79 {
80 //非指定类型图片不进行下载,直接返回原地址。
81 localImageSrc = remoteImageSrc;
82 return;
83 }
84
85 Uri uri = new Uri( remoteImageSrc );
86 if ( IsLocalSource( uri ) )
87 {
88 //本地(本网站下)图片不进行下载,直接返回原地址。
89 localImageSrc = remoteImageSrc;
90 return;
91 }
92
93 try
94 {
95 //自动创建一个目录。
96 DateTime now = DateTime.Now;
97 string datePath = string.Format( @"{0}\{1}\{2}\{3}" , now.Year , now.Month.ToString( "00" ) , now.Day.ToString( "00" ) , Guid.NewGuid( ).ToString( ) );
98
99 string localDirectory = System.IO.Path.Combine( Server.MapPath( savePath ) , datePath );
100 if ( !System.IO.Directory.Exists( localDirectory ) )
101 {
102 System.IO.Directory.CreateDirectory( localDirectory );
103 }
104
105 string localFilePath = System.IO.Path.Combine( localDirectory , fileName );
106
107 //不存在同名文件则开始下载,若已经存在则不下载该文件,直接返回已有文件路径。
108 if ( !System.IO.File.Exists( localFilePath ) )
109 {
110 Client.DownloadFile( uri , localFilePath );
111 }
112
113 string localImageSrc = ResolveUrl( "~/" + localFilePath.Replace( Server.MapPath( "~/" ) , string.Empty ).Replace( "\\" , "/" ) );
114
115 }
116 catch
117 {
118 //下载过程中出现任何异常都不抛出( 有点狠啊 :) ),仍然用远程图片链接。
119 localImageSrc = remoteImageSrc;
120 }
121
122 }
123
124
125 #endregion
126
127 private WebClient client;
128
129 /// <summary>
130 /// <see cref="System.Net.WebClient"/>
131 /// </summary>
132 public WebClient Client
133 {
134 get
135 {
136 if ( client != null )
137 {
138 return client;
139 }
140
141 client = new WebClient( );
142 client.Headers.Add( "user-agent" , "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2;)" );
143
144 return client;
145
146 }
147 }
148
149 /// <summary>
150 /// 判断Uri是否为本地路径
151 /// </summary>
152 /// <param name="uri"></param>
153 /// <returns></returns>
154 private bool IsLocalSource( Uri uri )
155 {
156 for ( int i = localhost.Length ; --i >= 0 ; )
157 {
158 if ( localhost[ i ].ToLower( ) == uri.Host.ToLower( ) )
159 {
160 return true;
161 }
162 }
163
164 return false;
165
166 }
167
168 /// <summary>
169 /// 检测文件类型是否为允许下载的文件类型
170 /// </summary>
171 /// <param name="extension">扩展名 eg: ".jpg"</param>
172 /// <returns></returns>
173 private bool IsAllowedDownloadFile( string extension )
174 {
175 for ( int i = allowImageExtension.Length ; --i >= 0 ; )
176 {
177 if ( allowImageExtension[ i ].ToLower( ) == extension.ToLower( ) )
178 {
179 return true;
180 }
181 }
182
183 return false;
184 }
185
186 </script>
187
188 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
189 <html xmlns="http://www.w3.org/1999/xhtml">
190 <head runat="server">
191 <title></title>
192 <style type="text/css">
193 body { margin: 0px; overflow: hidden; background-co