天天看點

Aspx頁面轉靜态頁面

為客戶在SharePoint的基礎上搭建了一個門戶,但是客戶又反映說首頁打開太慢,通過Fillder工具檢視,頁面打開速度大概在5秒左右。

   其實對于一個SharePoint站點來講,打開速度在3-4秒還是一個可以接受的範圍,但是我們的首頁放了太多的内容,包括圖檔、Flash、還有N多個WebPart,以至于要不斷的從資料庫互動。

   首先想到的解決方案是在頁面上加Cache,從Web層到資料層都可以考慮加Cache,但是這個方法很快就被否決了。因為SharePoint2007還不支援對自定義的頁面加載Cache。

   第二個解決方案,生成靜态頁面,當使用者通路時,讓其通路靜态頁面。

   關于生成靜态頁面,方法還是很多的,簡單列舉下:

   1、ASP.NET下Page的RenderControl方法本身就是傳回生成的HTML代碼,該方法在前面的随筆中有提到;

   2、Page.Server.Execute(url,stringwriter)方法,隻對該方法做了測試,有時間再深刻鑽研;

   簡單代碼: 

  public bool ExecAspxToHtml()

   {

   StringWriter strWriterHTML = new StringWriter();

   System.Web.UI.Page aspxPage = new System.Web.UI.Page();

   aspxPage.Server.Execute(strAspxUrl, strWriterHTML);//将aspx頁執行産生的html輸出到StringWriter中

   StreamWriter streamWriter = new StreamWriter(strHtmlFile, true, System.Text.Encoding.GetEncoding("GB2312"));

   streamWriter.Write(strWriterHTML.ToString());

   strWriterHTML.Close();

   streamWriter.Close();

   return true;

   } 

   3、模拟HttpWebRequest,擷取HttpWebResponse,采用這種方式來生成。

   簡單說頁面運作的機制:當我們在位址欄裡輸入網址後,第一次向伺服器抛Request,用戶端擷取到該Request産生的Response後,對其内部的Html代碼分析,對src,href等連結的檔案則繼續抛Request,擷取Response,知道頁面中需要的檔案都下載下傳到用戶端,頁面才能完全打開。

   決定了用第三種方案,對頁面生成的HTMl代碼,需要将其生成如 src 引用的連結檔案同時下載下傳到本地,對href引用的連結需要将其更改為絕對路徑。需要考慮的問題:

   1、對頁面内src 的Url進行分析,繼續繼續抛HttpWebRequest擷取該檔案,儲存到本地,同僚更改其src屬性為本地相對路徑。

   2、對頁面的href 的url進行分析,在其url前加上網站的伺服器名,成為絕對路徑。

   最主要的是這兩個問題,當然還有像Background中連結的圖檔。對于這些url,我都采用了 Regex的比對以及替換的方法。感覺正規表達式還是很強大的。

   代碼:

   //URL,使用者名都是寫在配置檔案中的

   public void ExecuteAspxToHtml()

   DistributeRequest(CreateWebRequest(strAspxUrl));

   }

   private HttpWebRequest CreateWebRequest(string url)

   HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);

   request.ContentType = "application/x-www-form-urlencoded";

   request.Method = "GET";

   request.Credentials = CreateCredential();

   return request;

   private ICredentials CreateCredential()

   ICredentials credential;

   //擷取配置檔案中的值

   if (!string.IsNullOrEmpty(GetAppValue("Domain")))

   credential = new NetworkCredential(GetAppValue("UserName"), GetAppValue("Password"), GetAppValue("Domain"));

   else

   credential = new NetworkCredential(GetAppValue("UserName"), GetAppValue("Password"));

   return credential;

   private void DistributeRequest(HttpWebRequest request)

   HttpWebResponse response = (HttpWebResponse)request.GetResponse();

   if (response.StatusCode == HttpStatusCode.OK)

   if (Directory.Exists(strHtmlPath))

   Directory.CreateDirectory(strHtmlPath);

   BinaryReader rsReader = new BinaryReader(response.GetResponseStream());

   byte[] buffer = rsReader.ReadBytes((int)response.ContentLength);

   //對其内部URl進行分析,擷取檔案

   GetContainUrl(response.ContentType, ref buffer);

   if (!CompareFile(buffer))

   FileStream fStream = new FileStream(strHtmlPath + strHtmlFile, FileMode.Create, FileAccess.Write);

   fStream.Write(buffer, 0, buffer.Length);

   fStream.Close();

   response.Close();

   private void DistributeRequest(HttpWebRequest request, string filePath, string fileName)

   try

   if (Directory.Exists(filePath))

   FileStream fStream = new FileStream(filePath + fileName, FileMode.Create, FileAccess.Write);

   catch(Exception ex)

   Console.WriteLine(ex.Message);

   Console.WriteLine(request.RequestUri.ToString());

   Console.WriteLine("URI錯誤");

   private void GetContainUrl(string ContentType, ref byte[] buffer)

   Encoding encode = System.Text.Encoding.GetEncoding("UTF-8");

   string strbuffer = encode.GetString(buffer);

   strbuffer = HandleSrc(strbuffer);

   strbuffer = HandleHref(strbuffer);

   buffer = encode.GetBytes(strbuffer);

   /// <summary>

   /// 對以src=""形式的連結,擷取其檔案儲存到本地

   /// </summary>

   /// <param name="strBuffer"></param>

   /// <returns></returns>

   private string HandleSrc(string strBuffer)

   Console.WriteLine("Handle the src property to get file");

   Console.WriteLine("*************************************"); 

   Regex regex = new Regex(srcRegex, RegexOptions.IgnoreCase);

   MatchCollection matchs = regex.Matches(strBuffer);

   foreach (Match item in matchs)

   if (item.Success)

   string matchContent = item.Value;

   string filePathName = GetFilePathName(matchContent);

   string fileUrl = GetFileUrl(matchContent);

   string filePath = filePathName.Substring(0,filePathName.LastIndexOf('\\'));

   if (!Directory.Exists(strHtmlPath + filePath))

   Directory.CreateDirectory(strHtmlPath + filePath);

   //if (!IsUrlFileExist(strHtmlPath, filePathName))

   //{

   DistributeRequest(CreateWebRequest(fileUrl), strHtmlPath, filePathName);

   //}

   Console.WriteLine("*************************************************"); 

   Console.WriteLine("Handle the src property and get file completed");

   Console.WriteLine();

   //上邊的循環可以放在進行中再抛Request,這裡還沒有改回來

   return regex.Replace(strBuffer, new MatchEvaluator(SrcMatchHandle));

   private string HandleHref(string strBuffer)

   Console.WriteLine("Handle the href property to change the relative link to absolute link");

   Console.WriteLine("************************************************************************"); 

   Regex regex = new Regex(hrefRegex, RegexOptions.IgnoreCase);

   //MatchCollection matchs = regex.Matches(strBuffer);

   return regex.Replace(strBuffer, new MatchEvaluator(HrefMatchHandle));

   //傳回要替換的字元串,即本地的相對路徑

   //該方法在替換時也是周遊執行的,是以可以在該方法裡擷取檔案

   private string SrcMatchHandle(Match match)

   if (match.Success)

   return GetFileRelatvePath(match.Value);

   return match.Value;

   private string HrefMatchHandle(Match match)

   return match.Value.Insert(match.Value.IndexOf('/'), strAspxPath); 

   其實還是投機了,因為客戶看中的隻是首頁,如果要讓我去做所有頁面的靜态化,那可真是頭疼,涉及到的各種各樣的連結都需要考慮。

   現在開發工作已經完成,打算做成一個Windos服務部署到伺服器,定時更新頁面。還是第一次,正在研究,有經驗的朋友可以探讨下。

   目标是為了解決SharePoint首頁反應慢的,不過技術全是.Net的技術。  

本文轉自左正部落格園部落格,原文連結:http://www.cnblogs.com/soundcode/archive/2010/12/24/1916391.html,如需轉載請自行聯系原作者