这两天在做报表的导出功能,做了多年的开发,对代码的严谨性自然有了一些自我约束,对于这种与业务无关的通用外部处理,都觉得应该将其划分为外部的服务,做处理调用。所以我就想到采用一般处理程序来做文件的下载,前端使用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则能够为良好的互 操作性提供最可靠的保证。
发现了错误就记录以下,对于以后再发现类似的问题也方便查找解决方案。