zoukankan      html  css  js  c++  java
  • ASP.NET中二进制流下载文件时进度条的使用

    说明

    在下载大文件时,页面会进入假死状态,于是加上一个进度条以标识后台程序正在运行。

    目前,做的进度条并不是实时的,并不会根据程序执行的进度正确显示。

    目前是将进度条定时加载到90%,然后停止,等待后台执行完成时,修改标志位以隐藏进度条。

    实现代码

    js设置cookie

    /****************************获取和设置cookie 开始***********************************/
    //获取cookie
    function getCookie(name) {
        var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"); //正则匹配
        if (arr = document.cookie.match(reg)) {
            return unescape(arr[2]);
        }
        else {
            return null;
        }
    }
    //设置自定义过期时间cookie
    function setCookie(name, value, time) {
        var msec = getMsec(time); //获取毫秒
        var exp = new Date();
        exp.setTime(exp.getTime() + msec * 1);
        document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
    }
    
    //将字符串时间转换为毫秒,1秒=1000毫秒
    function getMsec(DateStr) {
        var timeNum = str.substring(0, str.length - 1) * 1; //时间数量
        var timeStr = str.substring(str.length - 1, str.length); //时间单位前缀,如h表示小时
    
        if (timeStr == "s") //20s表示20秒
        {
            return timeNum * 1000;
        }
        else if (timeStr == "h") //12h表示12小时
        {
            return timeNum * 60 * 60 * 1000;
        }
        else if (timeStr == "d") {
            return timeNum * 24 * 60 * 60 * 1000; //30d表示30天
        }
    }
    
    //删除cookie
    function delCookie(name) {
        var exp = new Date();
        exp.setTime(exp.getTime() - 1);
        var cval = getCookie(name);
        if (cval != null) {
            document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
        }
    }
    //检查cookie
    function checkCookie() {
        username = getCookie('username')
        if (username != null && username != "")
        { alert('Welcome again ' + username + '!') }
        else
        {
            username = prompt('Please enter your name:', "")
            if (username != null && username != "") {
                setCookie('username', username, 365)
            }
        }
    }
    /*扩展使用*/
    
    //查看导出结束标志位,是否为指定的值
    function checkExportEndSign(ExportEndSignCookieName) {
        var ExportCookieValue = getCookie(ExportEndSignCookieName);//获取cookie的值          
        if (ExportCookieValue != "" && ExportCookieValue != null && ExportCookieValue != undefined && ExportCookieValue == "complete") {
            return true;
        }
        else {
            return false;
        }
    }
    /****************************获取和设置cookie 结束***********************************/

    C#后台添加cookie

    string shid_ExportCookieName = hid_ExportEndSignCookieName.Value;
    HttpCookie cookie = HttpContext.Current.Request.Cookies[shid_ExportCookieName];
    if (cookie == null)
    {
        cookie = new HttpCookie(shid_ExportCookieName);
    }
    cookie.Value = "complete";
    HttpContext.Current.Response.AppendCookie(cookie);

    需要的js和css

    <link href="/script/ext3.4/resources/css/ext-all.css" rel="stylesheet" type="text/css" />
    <script src="/script/ext3.4/adapter/ext/ext-base.js" type="text/javascript"></script>
    <script src="/script/ext3.4/ext-all.js" type="text/javascript"></script>

    ext的进度条,初始化、运行、隐藏

    <script type="text/javascript">
        /*进度条 相关js*/
        //声明需要使用的对象
        var progressBarExt;//ext进度条对象
        var progressBarExt_isEnd;//ext进度条是否结束(操作执行完成,将标志位置1,进度条循环递增不会再执行)
        //进度条对象-初始化
        function ProcessBarExt_Init(bar_title) {
            progressBarExt = Ext.Msg.show({
                title: bar_title,
                msg: "数据过大,需要等待一段时间!",
                progress: true,
                 300
            });
            progressBarExt_isEnd = 0;//初始化为0,未结束
            progressBarExt.updateProgress(0, "0%");//初始化为0%,刚开始
            Ext.onReady(ProcessBarExt_Run);
        }
        //进度条对象-开始执行
        function ProcessBarExt_Run() {
            var count = 0;
            var bartext = "";
            var curnum = 0;
            Ext.TaskMgr.start({
                run: function () {
                    count++;
                    if (count < 10 && progressBarExt_isEnd == 0) {
                        curnum = count / 10;
                        bartext = curnum * 100 + "%";
                        progressBarExt.updateProgress(curnum, bartext);
                    }
                },
                interval: 500
            })
        }
        //进度条对象-进度到100%且隐藏
        function ProcessBarExt_Hide() {
            progressBarExt_isEnd = 1;
            progressBarExt.updateProgress(10, "100%");
            setTimeout(function () { progressBarExt.hide(); }, 500);
        }
    </script>

    实现过程

    进度条 js使用的是:EXT

    核心思路:使用  cookie  标识后台操作执行完成。

    js+ajsx实现

    这种方式比较简单,直接看代码。

    function fun_Login() {
        ProcessBarExt_Init("登录");//初始化进度条对象
        ProcessBarExt_Run();//进度条对象 开始加载
        $.ajax({
            type: "POST",
            dataTye: "json",
            url: "/pages/Login.ashx",
            data: { type: 1},
            success: function (result) {
                if (result == "1") {
                    
                    alert("执行成功");
                }
                else{
                    alert("执行失败");
                }
                ProcessBarExt_Hide();
            },
            error: function () {
                alert("执行出错"); 
                ProcessBarExt_Hide();            
            }
        });    
    }

    aspx实现

    这个比较麻烦,经大佬指点 外加调试才实现。

    前言,之前做过类似的功能,所以先将 下载文件方法中的curContext.Response.End(); 代码删除掉了。否则,HTTP请求会结束,不会再执行后面的代码。

    几种思路

    (1)使用cookie

    此方法为最终方案,在实际项目中使用。

    设置一个cookie以标识后台程序是否执行完成。

    一个隐藏域,保存每次点击下载时随机生成的cookie名称,变量ExportEndSignCookieName保存,

    后台执行完操作时,根据添加一个cookie,name即为前台随机生成的保存到隐藏域中的值,value为"complete",

    前台,使用js的定时器循环获取cookie的值,

    如果cookie的值为后台设定的"complete",则隐藏进度条、删除js定时器、删除当前cookie。

    js代码

    <!--导出文件时 随机生成的cookie名称-->
    <asp:HiddenField ID="hid_ExportEndSignCookieName" runat="server" ClientIDMode="Static" />
    
    <script type="text/javascript">
        var tExportCookie;//定时器-查看后台是否执行完成
        var ExportEndSignCookieName="";//随机生成的cookie名称-查看后台是否执行完成
        //导出Excel,添加进度条
        function lbtnExport_click(){
            if(confirm('是否导出所查询的数据?')){                
                ExportEndSignCookieName=Math.random();//生成随机的cookie名称
                $("#hid_ExportEndSignCookieName").val(ExportEndSignCookieName);//cookie名称赋值给隐藏域
                ProcessBarExt_Init("导出Excel");//初始化进度条对象
                ProcessBarExt_Run();//进度条对象 开始加载
                tExportCookie = window.setInterval(fun_ExportEndSign,20);//定时循环,查看导出操作是否完成
                return true;
            }
            else{
                return false;
            }
        }  
        //查看导出是否结束,complete
        function fun_ExportEndSign(){       
            if(checkExportEndSign(ExportEndSignCookieName)){
                ProcessBarExt_Hide();//进度条隐藏
                window.clearInterval(tExportCookie); //删除定时器
                delCookie(ExportEndSignCookieName);//删除cookie
            }
        }
    </script>

    后台代码

    /// <summary>
    /// 导出方法
    /// </summary>
    private void ExportExcelByProc()
    {
        string tempWhere = "本次查询";            
        SqlParameter[] sqlParameters =
        { 
            new SqlParameter("@StartIndex",1), 
            new SqlParameter("@EndIndex",int.MaxValue)
        };
        DataSet ds = ExecuteStoredProcedureByDSNameEx("PersonInfo_List", "Business",sqlParameters);
        if (ds != null && ds.Tables != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
        {
            string sheetname = "个人建档管理表";           
            string[] colsCols = { "sNo"};
            string[] colsNames = { "档案编号"};
            BF.Web.App_Code.ExcelHelper.ExportHasWhereToWeb(sheetname + ExportExcelRule() + ".xls", ds.Tables[0], sheetname, sheetname, tempWhere, colsCols, colsNames);           
            string shid_ExportCookieName = hid_ExportEndSignCookieName.Value;
            HttpCookie cookie = HttpContext.Current.Request.Cookies[shid_ExportCookieName];
            if (cookie == null)
            {
                cookie = new HttpCookie(shid_ExportCookieName);
            }
            cookie.Value = "complete";
            HttpContext.Current.Response.AppendCookie(cookie);
        }
        else
        {
            Messages("当前无查询结果,请重新查询!");
        }
    }

    (2)后台调用js方法

    此方法,未实现需求。

    在后台注册js,去调用前台的js

    在下载文件方法的最后面curContext.Response.BinaryWrite(); 加上了上面的代码,

    但是,当HTTP请求执行了下载文件的操作后,就结束了,并没有执行js的方法。

    string ExtMsg = @"Ext.MessageBox.show({title: '系统提示',msg: '" + msg + "',buttons: {ok:'确  定'},icon: 'ext-mb-info'});";
    ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "click", ExtMsg, true);

    (3)使用Hidden隐藏域

    此方法,未实现需求。

    使用 Hidden做标志位,前台js进行监视,当隐藏域 触发 change事件时,去执行进度条的隐藏操作。

    但调试时,当后台代码执行完成后(也执行了隐藏域的赋值),但是前台的js监视,却捕获不到change事件。

    是不是这个赋值,将页面进行了刷新,或是这个赋值操作根本没有提交,反正没有起到作用。

    (4)iframe下载

    此方法,未进行测试,不知道效果如何。

    使用iframe进行下载,监视iframe的加载完毕,然后进行进度条的隐藏。

    此方法,将隐藏进度条的操作全部放到了js中,但是需要创建一个新的页面。

     

     

  • 相关阅读:
    synchronized锁机制 之 代码块锁(转)
    执行mvn 报错 source-1.5 中不支持 diamond运算符
    Git常用命令及场景
    mysql数据库导入与导出
    Linux磁盘空间分析及清理(df、du、rm)
    IIs配置文件存放路径
    解决SQLite database is locked
    C#测试web服务是否可用
    Jquery easyui-combobox 的一个BUG
    iframe自适应方法
  • 原文地址:https://www.cnblogs.com/masonblog/p/10137599.html
Copyright © 2011-2022 走看看