做导出一直遇到个问题就是不能用ajax实现一步导出文档,即导出加下载。今天突然想到可以分开来做就上网搜了下

问题说明:Ajax是无法实现文件传输的,本文只是模拟了Ajax不刷新页面就可以请求并返回数据的效果。实质上还是通过提交form表单来返回文件流的输出。

分步实现逻辑:

  1. ajax请求服务器,访问数据库,根据查询到的数据生成一个数据文件,返回前台一个json对象(可放置生成成功标记,文件路径等信息)。
  2. 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()
    }