做导出一直遇到个问题就是不能用ajax实现一步导出文档,即导出加下载。今天突然想到可以分开来做就上网搜了下
问题说明:Ajax是无法实现文件传输的,本文只是模拟了Ajax不刷新页面就可以请求并返回数据的效果。实质上还是通过提交form表单来返回文件流的输出。
分步实现逻辑:
- ajax请求服务器,访问数据库,根据查询到的数据生成一个数据文件,返回前台一个json对象(可放置生成成功标记,文件路径等信息)。
- ajax success回调函数部分,根据返回的json对象,调用手写的js下载文件的方法,实现页面无刷新下载文件。
贴上部分代码供参考:
js代码:
1. js写一个动态创建并提交form表单的方法,依赖于jQuery插件。
// 文件下载
jQuery.download = function (url, method, filedir, filename) {
jQuery('<form action="' + url + '" method="' + (method || 'post') + '">' + // action请求路径及推送方法
'<input type="text" name="filedir" value="' + filedir + '"/>' + // 文件路径
'<input type="text" name="filename" value="' + filename + '"/>' + // 文件名称
'</form>')
.appendTo('body').submit().remove();
};
2. 查询数据,输出到文件,保存到服务器,并调用download方法实现下载
//ajax交互导出文档并获取文档路径及预下载文件名,返回格式{\"result\":\"success\",\"filePath\":\"\",\"fileName\":\"\"}
function DownFilesAjax(url, prams, downurl) {
showLoading(true);//调用加载动画http://spin.js.org/
$.ajax({
type: 'POST',
dataType: 'json',
async: false,
url: url,// 生成文件,保存在服务器
data: prams,
success: function (data) {
if (data.result == "success") {
$.download(downurl, 'post', data.filePath, data.fileName); // 下载文件
showLoading(false);//隐藏加载动画http://spin.js.org/
} else {
alert("数据导出失败!");
showLoading(false);
}
},
error: function (XMLHttpRequest, textStatus, e) {
//console.log("oilDetection.js method exportOilDetection" + e);
alert("数据传输发生错误,请联系管理员!");
showLoading(false);
}
});
}
附上spin加载动画调用js及其容器的遮罩样式。
调用js:
var opts = {
lines: 9, // 花瓣数目
length: 0, // 花瓣长度
width: 10, // 花瓣宽度
radius: 15, // 花瓣距中心半径
corners: 1, // 花瓣圆滑度 (0-1)
rotate: 0, // 花瓣旋转角度
direction: 1, // 花瓣旋转方向 1: 顺时针, -1: 逆时针
color: '#fff', // 花瓣颜色
speed: 1, // 花瓣旋转速度
trail: 60, // 花瓣旋转时的拖影(百分比)
shadow: false, // 花瓣是否显示阴影
hwaccel: false, //spinner 是否启用硬件加速及高速旋转
className: 'spinner', // spinner css 样式名称 easyui里用这个类样式,若引用了easyui.css务必换个类名,其他前端框架未知
zIndex: 2e9, // spinner的z轴 (默认是2000000000)
top: '50%', // spinner 相对父容器Top定位 单位 px
left: '50%'// spinner 相对父容器Left定位 单位 px
};
var spinner = new Spinner(opts);
//显示与隐藏加载动画
function showLoading(result) {
var spinContainer = document.getElementById("foo");
if (result) {
var target = $(spinContainer).get(0);
spinner.spin(target);
spinContainer.style.height = document.documentElement.clientHeight + "px";
$(spinContainer).show();
} else {
spinner.spin();
$(spinContainer).hide();
}
}
遮罩样式:
#foo {
position: fixed;
left: 0;
top: 0;
_position: absolute;
width: 100%;
background: #000;
opacity: 0.5;
filter: alpha(opacity=50);
z-index: 999;
display:none;
}
以下一般处理程序中的相关代码。
导出文档:
public void ExportALLNianDuGongZuo(HttpContext context)
{
string result = string.Empty;
string Name = DateTime.Now.Year + "导出的文件" + ".xls";//下载文档名
try
{
#region 导出过程
DataTable dt = new DataTable();
DataColumn dc = null;
dc = dt.Columns.Add("序号", Type.GetType("System.Int32"));
dc.AutoIncrement = true;//自动增加
dc.AutoIncrementSeed = 1;//起始为1
dc.AutoIncrementStep = 1;//步长为1
dc.AllowDBNull = false;//
dc = dt.Columns.Add("col1", Type.GetType("System.String"));
dc = dt.Columns.Add("col2", Type.GetType("System.String"));
dc = dt.Columns.Add("col3", Type.GetType("System.String"));
dc = dt.Columns.Add("col4", Type.GetType("System.String"));
dc = dt.Columns.Add("col5", Type.GetType("System.String"));
IList<object> list = object.FindAll(@"IsEnable=1", "GOrder, PaiXu", null, 0, 0);//数据列表
foreach (var item in list)
{
DataRow newRow;
newRow = dt.NewRow();
newRow["col1"] = item.Name;
newRow["col2"] = item.Ext3;
newRow["col3"] = item.XieZuoDeptName;
newRow["col4"] = item.Ext2;
newRow["col5"] = IsShangHui.Trim();
dt.Rows.Add(newRow);
}
MemoryStream ms = new MemoryStream();
string Path = context.Server.MapPath("~/UploadFile/" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls");//文件保存地址
string templatePath = context.Server.MapPath("~/UploadFile/模版.xls");//所用模版地址
ms = NPOIExcelHelper.DataTableToExcel(dt, templatePath, 2);//详见NPOI导出execl
using (FileStream fs = new FileStream(Path, FileMode.Create, FileAccess.Write))
{
byte[] data = ms.ToArray();
fs.Write(data, 0, data.Length);
fs.Flush();
}
#endregion
result = "{\"result\":\"success\",\"filePath\":\"" + ReplaceString(Path) + "\",\"fileName\":\"" + Name + "\"}";
}
catch (Exception ex)
{
result = "{\"result\":\"fail\"}";
Unionstars.Trace.Log.WriteLine("导出发生错误:【" + ex + "】");
}
context.Response.ContentType = "application/Json";
context.Response.Write(result);
context.Response.End();
}
ajax无法传输文件,另新建web页面用来下载即可。
下载文档页面后台代码(前台删得只剩第一句即可):
protected void Page_Load(object sender, EventArgs e)
{
string fileName = Request["filename"];//下载文档名
string filePath = Request["filedir"];
FileInfo fileInfo = new FileInfo(filePath);
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
String userAgent = System.Web.HttpContext.Current.Request.UserAgent;
//判断是否为ie10以下及ie11浏览器
if (userAgent.Contains("MSIE") || userAgent.Contains("rv:11"))
{
fileName = System.Web.HttpUtility.UrlEncode(fileName);
}
Response.AddHeader("Content-Disposition", string.Format("attachment;filename=\"{0}\"", fileName));
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.AddHeader("Content-Transfer-Encoding", "binary");
Response.ContentType = "application/octet-stream";
Response.ContentEncoding = System.Text.Encoding.GetEncoding("gb2312");
Response.WriteFile(fileInfo.FullName);
Response.Flush();
Response.End();
}
终极方法,哈哈哈,留到最后
function download(url, downLoadFileRename) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true); // 也可以使用POST方式,根据接口
xhr.responseType = "blob"; // 返回类型blob
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.onload = function () {
// 请求完成
if (this.status === 200) {
// 返回200
var blob = this.response;
var reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
reader.onload = function (e) {
// 转换完成,创建一个a标签用于下载
var a = document.createElement('a');
a.download = downLoadFileRename;
a.href = e.target.result;
$("body").append(a); // 修复firefox中无法触发click
a.click();
$(a).remove();
}
}
};
// 发送ajax请求
xhr.send()
}