目 錄
1. Devexpress ASPxGridView的ASPxGridViewExporter.1
(1)使用.Net Framework框架中的HtmlDocument.3
(2)使用Codeplex第三方控件:Html Agility Pack.3
(1) 公共頁面元素保存(WebControlExporter)類...4
(2) 文檔保存類型枚舉(DocumentType)...4
需求
用戶可將一頁面的全部或指定的部分選擇性的保存至本地,並且可選擇性的設置保存格式(如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
}
}