將頁面(元素)保存至客戶端

 

 

 

頁面(元素)客戶端本地保存

 

 

 

 

 

 

 

 



需求

用戶可將一頁面的全部或指定的部分選擇性的保存至本地,並且可選擇性的設置保存格式(如MS/Word、MS/Excel、HTML)。

   在將頁面(或指定部分)保存至客戶端本地時,會出現下圖所示的問題:包含多餘無效的元素。要求剔除無關的頁面控件。

方案選擇

1.  Devexpress ASPxGridView的ASPxGridViewExporter

方案:在包含ASPxGridView控件的頁面中,使用ASPxGridViewExporter導出數據表格。

問題:這種方法導出的樣式效果有限制,只能是一行一行記錄展示的形式,可以包含表頭。但是不能實現將我們自定義複雜表格樣式原樣導出保存的功能。

2.  ActiveX對象

方案:使用ActiveX對象。

問題:此方案對客戶端的瀏覽器的安全設置有要求。

3.  JS構造請求回覆(Response)

方案:在頁面中使用JS打開一個全新的請求回覆(Response),將頁面(或指定部分)寫入Response中,並使用文檔對象模型(Document)中的“exeCommand”方法執行保存命令(“SaveAs”),瀏覽器將自動填出“保存文件”提示框。

代碼示例:

問題:客戶端瀏覽器(MS/IE)基於安全的考慮,只能存爲“HTML”或平面文件(“.csv”)。雖然將文件的後綴改寫後(如改爲“.doc”),MS/Office可打開文件。但是不符合用戶的操作習慣,特別是計算機基礎不熟練的用戶。

4.  服務器端構造請求回覆(Response)

方案:用戶在頁面中點擊按鈕發出“保存至本地”請求後,在服務器端構造出相應的回覆(Response),將要求的頁面(或指定的部分)寫入回覆中。同時設置回覆的文檔類型(Content-Type)及編碼等(文檔頭)信息。

注意需要去除需要進行導出的ASPX頁面的自驗證功能:

共有2步:

1、 配置頁面“@Page”;

<%@ PageEnableEventValidation="false"%>

 

2、 重寫“VerifyRenderingInServerForm”方法;

  protected void btnXlsExport_Click(objectsender, EventArgs e)

{

WebControlExporter.ExportControl(exportPart,DocumentType.Excel,"**文件");

}

 

 

執行方案

採用“服務器端構造請求回覆(Response)”方案。針對“需求”中描述的刪除無效元素的要求,方案如下:

1.      刪除無效元素方案

(1)使用.Net Framework框架中的HtmlDocument

方案:使用HtmlDocument進行“HTML代碼”的修改,如刪除特定的元素。

問題:HtmlDocument對象只能通過WebBrowser對象獲取,但是在使用WebBrowser對象的時候,修改在一個全新的線程中啓動,同時該線程必須是單線程(STA),不能在原線程中執行。

(2)使用Codeplex第三方控件:Html Agility Pack

方案:使用該控件可以輕鬆的實現針對HTML的操作(官網稱可與“JQuery”媲美),其實現原理是將指定的源(URL、I0.Stream、HTML)解析爲XML格式,同時支持使用MS .Net框架中的XPath語法功能。

2.  代碼設計

(1)    公共頁面元素保存(WebControlExporter)類

(2)    文檔保存類型枚舉(DocumentType)

(3)    WebControlExporter公共接口

代碼參見附件

 


 

附件:

1.  公共頁面元素保存(WebControlExporter)類代碼

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Linq;

usingSystem.Web;

usingSystem.Web.UI;

usingHtmlAgilityPack;

usingSystem.IO;

usingADMM.Lib;

 

namespace ADMM.Web.CommonTools

{

    public class WebControlExporter

    {

 

       ///<summary>

       ///Web控件導出

       ///</summary>

       ///<param name="source">要保存的頁面控件</param>

       ///<param name="type">類型(DocumentType枚舉)</param>

       ///<param name="fileName">默認保存的文件名稱</param>

       public staticvoid ExportControl(System.Web.UI.Control source,DocumentTypetype, string fileName)

       {

           var responser = source.Page.Response;

            SetHeaderContentType(responser,type, fileName);

           //關閉控件的視圖狀態

           source.Page.EnableViewState = false;

 

           //初始化HtmlWriter

           System.IO.StringWriter writer =new System.IO.StringWriter();

           System.Web.UI.HtmlTextWriterhtmlWriter =new System.Web.UI.HtmlTextWriter(writer);

           source.RenderControl(htmlWriter);

 

           //剔除或隱藏相關元素

           var html =htmlWriter.InnerWriter.ToString();

           HtmlDocument doc = new HtmlDocument();

           doc.LoadHtml(html);

           HtmlNode node = doc.DocumentNode;

           //SetImagesHide(node);

           RemoveNodes(node.SelectNodes("//img"));

           RemoveNodes(node.SelectNodes("//image"));

           RemoveNodes(node.SelectNodes("//script"));

           RemoveNodes(node.SelectNodes("//*[@class=\"dxgvFilterRow\"]"));

           RemoveNodes(node.SelectNodes("//*[@class=\"dxgvFilterRow_"+GlobalConfiguartion.PageTheme + "\"]"));

           RemoveNodes(node.SelectNodes("//*[@class=\"dxgvFilterBar\"]"));

           RemoveNodes(node.SelectNodes("//*[@class=\"dxgvFilterBar_"+GlobalConfiguartion.PageTheme + "\"]"));

           //刪除Loadding Panel

           RemoveNodes(node.SelectNodes("//*[@class=\"dxgvLoadingPanel\"]"));

            RemoveNodes(node.SelectNodes("//*[@class=\"dxgvLoadingPanel_" +GlobalConfiguartion.PageTheme + "\"]"));

           //刪除字段列表面板

           RemoveNodes(node.SelectNodes("//*[@class=\"dxpcControl\"]"));

           RemoveNodes(node.SelectNodes("//*[@class=\"dxpcControl_"+GlobalConfiguartion.PageTheme + "\"]"));

           //設置GridView的表格邊框

           AppendNodesAttribute(node.SelectNodes("//*[@class=\"dxgvTable\"]"),"border","1");

           AppendNodesAttribute(node.SelectNodes("//*[@class=\"dxgvTable_"+GlobalConfiguartion.PageTheme + "\"]"), "border","1");

           AppendNodesAttribute(node.SelectNodes("//*[@class=\"dxgvTable\"]"),"borderColor","black");

           AppendNodesAttribute(node.SelectNodes("//*[@class=\"dxgvTable_"+GlobalConfiguartion.PageTheme + "\"]"), "borderColor","black");

 

           //輸出

           responser.Write(node.InnerHtml);

           responser.End();

       }

 

       ///<summary>

       ///HTML節點元素添加屬性

       ///</summary>

       ///<param name="nodes">HTML節點集合</param>

       ///<param name="attrName">屬性名稱</param>

       ///<param name="attrValue">屬性值</param>

       private staticvoid AppendNodesAttribute(HtmlNodeCollection nodes,stringattrName, string attrValue)

       {

           if (nodes == null)

                return;

           foreach (HtmlNodecnodein nodes)

           {

                if(cnode.Attributes[attrName] !=null)

                {

                   cnode.Attributes[attrName].Value = attrValue;

                }

                else

                {

                    cnode.Attributes.Add(attrName,attrValue);

                }

           }

       }

 

       ///<summary>

       ///設置請求回覆頁面頭部信息中的文檔類型

       ///</summary>

       ///<param name="responser">請求的回覆對象</param>

       ///<param name="type">保存的目標文檔類型(DocumentType枚舉)</param>

       ///<param name="fileName">保存的目標文件名稱</param>

       private staticvoid SetHeaderContentType(HttpResponse responser,DocumentTypetype, string fileName)

       {

           

           var tmpFileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8).ToString();

 

           //設置Http的頭信息,編碼格式

           if (type == DocumentType.Excel)

           {

                //Excel

                responser.AppendHeader("Content-Disposition","attachment;filename=" + tmpFileName + ".xls");

                responser.ContentType = "application/ms-excel";

           }

           else if(type == DocumentType.Word)

           {

                //Word

                responser.AppendHeader("Content-Disposition","attachment;filename=" + tmpFileName + ".doc");

                responser.ContentType = "application/ms-word";

           }

           responser.Charset = "UTF-8";

           responser.ContentEncoding = System.Text.Encoding.UTF8;

       }

 

       ///<summary>

       ///隱藏HTML節點中的所有圖片

       ///</summary>

       ///<param name="node">HTML節點</param>

       private staticvoid SetImagesHide(HtmlNodenode)

       {

           SetNodesHide(node.SelectNodes("//img"));

           SetNodesHide(node.SelectNodes("//image"));

       }

 

       ///<summary>

       ///隱藏節點

       ///</summary>

       ///<param name="nodes">待隱藏的節點集合</param>

       private staticvoid SetNodesHide(HtmlNodeCollectionnodes)

       {

           if (nodes == null|| nodes.Count == 0)

                return;

           AppendNodesStyle(nodes, "display:none;");

       }

 

       ///<summary>

       ///給節點擴展樣式(追加的方式)

       ///</summary>

       ///<param name="nodes">待添加樣式的節點集合</param>

       ///<param name="styleValue">樣式內容</param>

       private staticvoid AppendNodesStyle(HtmlNodeCollectionnodes,string styleValue)

       {

           if (nodes == null)

                return;

           foreach (HtmlNodecnodein nodes)

           {

                if(cnode.Attributes["style"] !=null)

                {

                    cnode.Attributes["style"].Value += styleValue;

                }

                else

                {

                    cnode.Attributes.Add("style", styleValue);

                }

           }

       }

 

       ///<summary>

       ///刪除節點

       ///</summary>

       ///<param name="nodes">待刪除的節點集合</param>

       private staticvoid RemoveNodes(HtmlNodeCollectionnodes)

       {

           if (nodes == null)

                return;

            foreach(HtmlNode rninnodes)

           {

                rn.Remove();

           }

       }

 

    }

 

    //文檔類型

    public enum DocumentType

    {

       ///<summary>

       ///微軟的Word 2003

       ///</summary>

       Word,

       ///<summary>

       ///微軟的Excel 2003

       ///</summary>

       Excel

    }

}

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章