zoukankan      html  css  js  c++  java
  • 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;

  • 相关阅读:
    HYSBZ 3813 奇数国
    HYSBZ 4419 发微博
    HYSBZ 1079 着色方案
    HYSBZ 3506 排序机械臂
    HYSBZ 3224 Tyvj 1728 普通平衡树
    Unity 3D,地形属性
    nginx 的naginx 种包含include关键字
    Redis 出现NOAUTH Authentication required解决方案
    mysql 8.0出现 Public Key Retrieval is not allowed
    修改jar包里的源码时候需要注意的问题
  • 原文地址:https://www.cnblogs.com/mingmingruyuedlut/p/3056581.html
Copyright © 2011-2022 走看看