• Asp.net 前后台操作cookie 实现数据的循环下载


    首先简单叙述一下问题的由来,由于数据的获取是通过调用相应的WebService从其他系统获取的,因此每次获取的数据有限制,并且需要要满足一次最多只能下载一定数量的记录,若filter出来的数据大于这个最大值的时候,我们就要分批循环进行下载。由于每次从前台调用后台方法都是一次post-back过程,那么记录上一次的下载位置以及整体的filter条件 就不能用简单的局部变量进行记录了。因此这里才用到了cookie进行记录,并且后续的下载要自动的弹出popup,所以前台要简单的写个timer job,定时的检测对应的cookie,若条件满足那么弹出popup,若所有的数据都下载完成,那么关闭这个timer job。当然了第一次触发timer job的时机我们可以选择在用户第一次点击下载数据之后。

    接下来完整简单的叙述下载整体的设计流程:

    前台:对JQuery进行扩展实现对Cookie的操作 --> 模拟timer job定时对相应的Cookie进行检测

    后台:定义四个Cookie值(filter的条件、上一次下载的位置、继续下载、下载完成),前两个Cookie是后台取具体数据时用到,后两个是完成循环弹出popup用到 --> 根据第二个Cookie值的属性判断是否下载完成 --> 将第三个或者第四个Cookie添加到Response中 以提供前台的定时检测

    如下将主要的代码段贴出:

     1): 对JQuery进行扩展实现对Cookie的操作

    /*!
     * jQuery Cookie Plugin v1.3.1
     * https://github.com/carhartl/jquery-cookie
     *
     * Copyright 2013 Klaus Hartl
     * Released under the MIT license
     */
    (function ($, document, undefined) {
    
        var pluses = /\+/g;
    
        function raw(s) {
            return s;
        }
    
        function decoded(s) {
            return unRfc2068(decodeURIComponent(s.replace(pluses, ' ')));
        }
    
        function unRfc2068(value) {
            if (value.indexOf('"') === 0) {
                // This is a quoted cookie as according to RFC2068, unescape
                value = value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
            }
            return value;
        }
    
        function fromJSON(value) {
            return config.json ? JSON.parse(value) : value;
        }
    
        var config = $.cookie = function (key, value, options) {
    
            // write
            if (value !== undefined) {
                options = $.extend({}, config.defaults, options);
    
                if (value === null) {
                    options.expires = -1;
                }
    
                if (typeof options.expires === 'number') {
                    var days = options.expires, t = options.expires = new Date();
                    t.setDate(t.getDate() + days);
                }
    
                value = config.json ? JSON.stringify(value) : String(value);
    
                return (document.cookie = [
                    encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value),
                    options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
                    options.path    ? '; path=' + options.path : '',
                    options.domain  ? '; domain=' + options.domain : '',
                    options.secure  ? '; secure' : ''
                ].join(''));
            }
    
            // read
            var decode = config.raw ? raw : decoded;
            var cookies = document.cookie.split('; ');
            var result = key ? null : {};
            for (var i = 0, l = cookies.length; i < l; i++) {
                var parts = cookies[i].split('=');
                var name = decode(parts.shift());
                var cookie = decode(parts.join('='));
    
                if (key && key === name) {
                    result = fromJSON(cookie);
                    break;
                }
    
                if (!key) {
                    result[name] = fromJSON(cookie);
                }
            }
    
            return result;
        };
    
        config.defaults = {};
    
        $.removeCookie = function (key, options) {
            if ($.cookie(key) !== null) {
                $.cookie(key, null, options);
                return true;
            }
            return false;
        };
    
    })(jQuery, document);

    2): 在Client端模拟timer job定时对相应的Cookie进行检测(每2秒钟检测一次)

    //=================================================
    // export activity monitor
    //=================================================
    var downloadJob;
    var exportCount = 0;
    function checkDownload() {
        clearInterval(downloadJob);
        downloadJob = setInterval(processDownloadStatus, 2000); //check cookie each 2 second
    }
    
    function closeDownload() {
        clearInterval(downloadJob);
        downloadJob = "undefined"; //mark
    }
    
    function processDownloadStatus() {
        var c1 = $.cookie("TradeDetailsExport-MoreExport");
        if (c1 != null && c1 != 'undefined' && c1 != '') {
            _spFormOnSubmitCalled = false; //continue post-back on SharePoint
            exportCount++;
            ExportMorePopUpClick(exportCount); //popup function
            $.cookie("TradeDetailsExport-MoreExport", null, { path: '/' });
            return;
        }
    
        var c2 = $.cookie("TradeDetailsExport-DoneExport");
        if (c2 != null && c2 != 'undefined' && c2 != '') {
            if ($.colorbox != null && $.colorbox != "undefined") {
                $.colorbox.close();
            }
            exportCount = 0;
            _spFormOnSubmitCalled = false; //continue post-back on SharePoint
            $.cookie("TradeDetailsExport-DoneExport", null, { path: '/' });
            setNoRecordText();
            closeDownload();
            return;
        }
    }

    3): 在Server端操作Cookie并且实现数据的下载

            public static void Export(int rows, bool needCookie, bool moreExport, Collection<string> columns)
            {
                HttpContext context = HttpContext.Current;
                System.Web.Script.Serialization.JavaScriptSerializer oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
    
                TradeDetailsRequest request = null; // class for query....
                TradeDetailsCursor tradeDetailsCursor = null; // class for mark download last key...
    
                if (context.Request.Cookies[TradesConstants.TRADE_DETAIL_REQUEST] != null)
                {
                    request = oSerializer.Deserialize<TradeDetailsRequest>(DecodeCookie(context, TradesConstants.TRADE_DETAIL_REQUEST));
                }
    
                if (context.Request.Cookies[TradesConstants.TRADE_DETAIL_CURSOR] != null)
                {
                    tradeDetailsCursor = oSerializer.Deserialize<TradeDetailsCursor>(DecodeCookie(context, TradesConstants.TRADE_DETAIL_CURSOR));
                }
    
                //// No request provided - return error
                if (request == null)
                {
                    // to-do: should redirect to an error page
                    context.Response.ContentType = "text/plain";
                    context.Response.Write("Error: No request found.");
                    context.Response.End();
                }
    
                //// Last Request does not match current - cannot be resuming
                //if (!request.Equals(lastRequest))
                if (!moreExport)
                {
                    tradeDetailsCursor = null;
                }
    
                //// Retrieve Trade Items
                TradeItems tradeItems = TradeDetailsFacade.GetTradeDetailRequest(request, rows, tradeDetailsCursor); // get data item based on query and last time key
    
                /// Prepare to respond With a CSV file
                context.Response.Clear();
    
                bool overLimit = tradeItems.LastKey.LastRecordStatus != TradesConstants.NO_MORE_RECORD_INDICATOR; // have more data to download next time
    
                if (needCookie)
                {
                    HttpCookie exportCookie = null;
                    if (overLimit)
                    {
                        exportCookie = new HttpCookie(TradesConstants.MORE_EXPORT);
                        exportCookie.Value = "1"; // arbitrary data; not used in code logic
                    }
                    else
                    {
                        exportCookie = new HttpCookie(TradesConstants.NO_MORE_EXPORT);
                        exportCookie.Value = "0"; // arbitrary data; not used in code logic
                    }
                    exportCookie.Expires.AddHours(1);
                    exportCookie.HttpOnly = false;
                    context.Response.Cookies.Add(exportCookie);
                }
    
                // Set Cursor Cookie
                HttpCookie tradeDetailsCursorCookie = new HttpCookie(TradesConstants.TRADE_DETAIL_CURSOR);
                tradeDetailsCursorCookie.Value = Encryption.EncryptString(oSerializer.Serialize(tradeItems.LastKey), TradesConstants.ENCRYPTION_KEY);
                tradeDetailsCursorCookie.Path = "/";
                tradeDetailsCursorCookie.Expires.AddHours(1);
                context.Response.Cookies.Add(tradeDetailsCursorCookie);
    
                // if there are no columns, use the default set.
                if (columns.Count < 1)
                {
                    columns = TradesConstants.AllTradeColumnFieldNames();
                }
    
    
                // do not buffer the output!
                string filename = TradesConstants.DEFAULT_EXPORT_FILENAME;
                context.Response.BufferOutput = false;
                context.Response.ContentType = "text/csv";
                context.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
    
                // iterate over trade entities
                for (int i = 0; i < tradeItems.Trades.Count; i++)
                {
                    // create the csv line, will need to pull the list from query string
                    context.Response.Write(tradeItems.Trades[i].GetCsvFormattedEntity(columns));
                }
                
                context.Response.End();
                context.Response.Flush();
    
            }
    
            private static string DecodeCookie(HttpContext context, string cookieName)
            {
                string encodedString = context.Request.Cookies[cookieName].Value;
                return Encryption.DecryptString(encodedString, TradesConstants.ENCRYPTION_KEY);
            }

    4): 一些用到的常量声明

        /// <summary>
        /// This class provides constants and mappings of constants for the RTTA aspect of FNX
        /// </summary>
        public static class TradesConstants
        {
            /// <summary>
            /// default export filename.
            /// </summary>
            public const string DEFAULT_EXPORT_FILENAME = "TradeDetails.csv";
    
            ///Export completion indicator.
            /// </summary>
            public const string NO_MORE_RECORD_INDICATOR = "C";
    
            ///More Export cookie name.
            /// </summary>
            public const string MORE_EXPORT = "TradeDetailsExport-MoreExport";
    
            ///No more Export cookie name.
            /// </summary>
            public const string NO_MORE_EXPORT = "TradeDetailsExport-DoneExport";
    
            /// <summary>
            /// Trade detail cursor cookie name.
            /// </summary>
            public const string TRADE_DETAIL_CURSOR = "TradeDetailsExport-TradeDetailsCursor";
    
            /// <summary>
            /// Trade detail request cookie name.
            /// </summary>
            public const string TRADE_DETAIL_REQUEST = "TradeDetailsExport-Request";
    
            /// <summary>
            /// Trade detail last request cookie name.
            /// </summary>
            public const string TRADE_DETAIL_LAST_REQUEST = "TradeDetailsExport-LastRequest";
        }

    ps:如果此行为是应用在SharePoint中的话,那么要修改对应的属性,来屏蔽postback的失效。 即:第二段代码中的 _spFormOnSubmitCalled = false;

  • 相关阅读:
    BZOJ 1003--[ZJOI2006]物流运输(最短路)
    BZOJ 1002--[FJOI2007]轮状病毒(高精度)
    BZOJ 1001--[BeiJing2006]狼抓兔子(最短路&对偶图)
    BZOJ 1719--[Usaco2006 Jan] Roping the Field 麦田巨画(几何&区间dp)
    BZOJ 2821--作诗(分块)
    BZOJ 2724--蒲公英(分块)
    BZOJ 2388--旅行规划(分块&单调栈&二分)
    用python操作Git
    JS常用到的日期函数
    Python3.7使用celery出现from . import async, base SyntaxError: invalid syntax错误
  • 原文地址:https://www.cnblogs.com/mingmingruyuedlut/p/3056581.html
Copyright © 2020-2023  润新知