這兩天在做報表的導出功能,做了多年的開發,對代碼的嚴謹性自然有了一些自我約束,對於這種與業務無關的通用外部處理,都覺得應該將其劃分爲外部的服務,做處理調用。所以我就想到採用一般處理程序來做文件的下載,前端使用Ajax做無刷新處理,代碼如下:
function QueryExcel() {
var data = Ext.getCmp("frmMain").GetValues();// 獲取json數據
Ext.Ajax.request({
url: '../Services/ReportExportHandler.ashx', // Webservice的地址以及方法名
jsonData: data,
method: 'POST',// poste 方式傳遞
success: function (result) {
// 調用成功處理
},
failure: function (result) {
// 調用失敗處理
}
});
}
一般處理程序實現文件下載的代碼:
string fileName = HttpUtility.UrlEncode(System.Text.Encoding.UTF8.GetBytes("111.csv"));
context.Server.ScriptTimeout = 600;
context.Response.ContentType = "application/octet-stream";
context.Response.Charset = "gb2312";
context.Response.AddHeader("Content-Disposition", string.Format("attachment;filename=\"{0}\"", fileName));
context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
DataTable dt = this.GetReportExcuteData(dto, paramsValues).Tables[0];
byte[] bs = ExportHelper.GetMemoryBytes(dt);
context.Response.BinaryWrite(bs);
context.Response.End();
將文件生成到內存的代碼:
/// <summary>
/// 從內存中獲取字節數組
/// </summary>
/// <param name="dt">數據表</param>
/// <returns>字節數組</returns>
public static byte[] GetMemoryBytes(DataTable dt)
{
// 先打印標頭
StringBuilder strColu = new StringBuilder();
StringBuilder strValue = new StringBuilder();
int i = 0;
try
{
MemoryStream ms = new MemoryStream();
byte[] bs;
for (i = 0; i <= dt.Columns.Count - 1; i++)
{
strColu.Append(dt.Columns[i].ColumnName);
strColu.Append(",");
}
strColu.Remove(strColu.Length - 1, 1); // 移出掉最後一個,字符
bs = System.Text.Encoding.Default.GetBytes(strColu.ToString() + "\r\n");
ms.Write(bs, 0, bs.Length);
foreach (DataRow dr in dt.Rows)
{
strValue.Remove(0, strValue.Length); // 移出
for (i = 0; i <= dt.Columns.Count - 1; i++)
{
strValue.Append(dr[i].ToString());
strValue.Append(",");
}
strValue.Remove(strValue.Length - 1, 1); // 移出掉最後一個,字符
bs = System.Text.Encoding.Default.GetBytes(strValue.ToString() + "\r\n");
ms.Write(bs, 0, bs.Length);
}
byte[] data = ms.GetBuffer();
ms.Close();
return data;
}
catch (Exception ex)
{
throw ex;
}
}
在處理時發現點擊按鈕沒有反應,起初我以爲是一般處理程序內部寫的有問題,但用瀏覽器的開發者工具查看請求和響應,發現響應的報頭跟響應的的內容都與預期的相同,說明我的一般處理程序沒有問題。後端沒問題,那就是前端的問題了,由於對於Ajax的處理不是非常瞭解,所以一直也沒有想到問題出在哪,後來我就發了個帖子問了一下,這才恍然大悟,原來Ajax可處理的數據格式是有要求的,引用資料原文:Jquery Ajax
另外還查到一篇關於 Ajax數據格式比較的博文,內容如下:
1.html
優點:html片段實現起來只需要很小的工作量。這種格式的外部數據可以通過一種簡單的方法加載並插入到頁面中,甚至連回調函數都不必使用。無需遍歷數據。
缺點:重用性差,外部文件必須與它們的目標容器緊密結合。
2.JavaScript
JavaScript文件能投提供極大的靈活性,但它卻不是一種真正的數據存儲機制。
3.json
優點:
json文件的結構使它可以方便地被重用。而且它們非常簡潔,也容易閱讀,讀取速度快。
缺點:
json文件中的錯誤可能導致頁面上的腳本靜默地終止運行,甚至還會帶來其它的負面影響,因此,這種數據必須由信得過的人仔細進行構建。
4.xml
優點:
xml文檔的可移植性是當之無愧的王者,xml已經成爲了web服務領域的“世界語”。xpath、dtd等都爲它增色不少,能夠對格式進行有效的驗證。
缺點:
xml格式的文件體積相對較大,解析和操作它們的速度要慢一些。
總結:
通過對以上各種數據格式優缺點的分析,我們知道在不需要與其它應用程序共享數據的情況下,以html片段提供外部數據一般來說都是最簡單的。如果數據需要重 用,而且其它應用程序也可能因此受影響,那麼在性能和文件大小方面具有優勢的json通常是不錯的選擇。而當遠程應用程序未知時,xml則能夠爲良好的互 操作性提供最可靠的保證。
發現了錯誤就記錄以下,對於以後再發現類似的問題也方便查找解決方案。