get参数过长的一种解决方案

1 篇文章 0 订阅

答案是:sessionStorage

背景

有个需求是对资讯进行预览(类似于发博客前预览下效果这样),一种很容易想到的简单办法是将预览的内容(如标题和正文)通过get请求传递到预览页中,js代码如下:

function previewNews(){
    var action = "XXXX" ;
    // 拿到页面中的标题和正文    
    var title = $("#title").val();
    var content = $("#content").val(); 

    var url = action+ "?title=" + encodeURIComponent(title) + "&content=" + encodeURIComponent(content); 
    window.open(url);//打开拼接后的url
}

这种方法在标题和正文字数不多的情况下是没有问题的。but问题是,资讯的正文字数却经常出乎意料地很长。多长呢?长到预览页面load啊load啊就是load不出来。查了查,这是因为浏览器或者服务器对url有长度限制(很多人包括我自己误解为是HTTP get方法对参数的限制,其实不是)。百度来的资料如下:

Microsoft Internet Explorer (Browser)
IE浏览器对URL的最大限制为2083个字符,如果超过这个数字,提交按钮没有任何反应。
Firefox (Browser)
对于Firefox浏览器URL的长度限制为65,536个字符。
Safari (Browser)
URL最大长度限制为 80,000个字符。
Opera (Browser)
URL最大长度限制为190,000个字符。
Google (Browser)
URL最大长度限制为8182个字符。
Apache (Server)
能接受最大url长度为8,192个字符。
Microsoft Internet Information Server(IIS)
能接受最大url的长度为16,384个字符。

而且,中文是以urlencode后的编码形式进行传递。如果浏览器的编码为UTF8的话,一个汉字最终编码后的字符长度为9个字符。(这句话也是百度来的,未经证实)这么算算,对于IE浏览器来说,标题和正文加起来最多能输入231个中文,超过了就完蛋。那么通过get方式传递参数预览这样的解决办法就变得毫无用处,因为资讯一般来说至少是三五百字的,必须寻找替代方案。

替代方案

想到的两种替代方案如下:

  1. 将预览内容post到服务端,根据一个唯一标识生成缓存(有效时间5分钟),将唯一标识返回到前端,前端通过get方式传递唯一标识请求预览逻辑,拿到缓存的内容后渲染到页面。需要说明的是这里的缓存必须是分布式的。
  2. 通过H5的会话缓存sessionStorage将预览内容存储在浏览器,打开预览页后从sessionStorage中拿到内容就可以渲染出页面了。

第一个解决方案需要用到分布式缓存,而我们的应用目前还没有引入分布式缓存,为了一个预览功能引入分布式缓存无论从时间成本来说还是其他成本,都不划算。怎么算都是使用sessionStorage更加便捷。

走近sessionStorage

sessionStorage,顾名思义,是浏览器基于session的一种本地存储方式。这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage并不是一种持久化的本地存储。与之相对应的另一种H5本地存储技术localStorage却是一种持久化的本地存储方式。结合资讯预览的需求,明显sessionStorage更适用。虽然之前并没有用过sessionStorage,但我还是义无反顾地将它应用在了这个需求上。其实它的使用方法还算挺简单的:

function previewNews(){
    var action = "XXX" ;

    var newsId = $("#id").val();//资讯的唯一标识
    var title = $("#title").val();
    var content = $("#content").val(); 
    //通过setItem方法存储value
    sessionStorage.setItem(newsId+"_title",title);
    sessionStorage.setItem(newsId+"_content",content);

    var url = action+ "?newsId=" + newsId; 
    window.open(url);
}

预览页取内容时这样写:

$(document).ready(function() {
    var newsId = $("#newsId").val();
    //通过getItem方法获取value
    var title = sessionStorage.getItem(newsId + "_title");
    var content = sessionStorage.getItem(newsId + "_content");

    $("#news_title").html(title);
    $("news_content").html(content);
});

简单的几行代码,解决了因为内容过长不能预览的问题。但是别慌,还有一个潜在的问题需要解决,那就是,sessionStorage对IE的支持不够好。换句话说,如果用户使用的是IE浏览器,那么还是会打不开预览页。怎么办呢?不用慌,早已经有人帮我们解决好了,网上一搜就有了。简单说,如果是IE浏览器,那么我们引入一个js插件,这个插件用cookie重写了sessionStorage的几个方法(setItem、getItem等),代码一看便知:
插件名:sessionStorage.js

/**
 *补充不支持sessionStorage的浏览器使用cookie代替
 * 使用:
 * sessionStorage.setItem("key","value");
 * sessionStorage.getItem("key");
 * */
if (!window.sessionStorage) {
    window.sessionStorage = {
        getItem: function(sKey) {
            if (!sKey || !this.hasOwnProperty(sKey)) {
                return null;
            }
            return unescape(document.cookie.replace(new RegExp("(?:^|.*;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"), "$1"));
        },
        key: function(nKeyId) {
            return unescape(document.cookie.replace(/\s*\=(?:.(?!;))*$/, "").split(/\s*\=(?:[^;](?!;))*[^;]?;\s*/)[nKeyId]);
        },
        setItem: function(sKey, sValue) {
            if (!sKey) {
                return;
            }
            document.cookie = escape(sKey) + "=" + escape(sValue) + "; path=/";
            this.length = document.cookie.match(/\=/g).length;
        },
        length: 0,
        removeItem: function(sKey) {
            if (!sKey || !this.hasOwnProperty(sKey)) {
                return;
            }
            document.cookie = escape(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
            this.length--;
        },
        hasOwnProperty: function(sKey) {
            return (new RegExp("(?:^|;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
        }
    };
    window.sessionStorage.length = (document.cookie.match(/\=/g) || window.sessionStorage).length;
}

将这个插件引入到用到sessionStorage的地方,就不怕IE不支持啦!

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
随着餐馆在纽约的重新开业,我注意到它们都已转向非接触式数字菜单。由于我最近一直在花时间研究无线应用,其中涉及使用MiniZed和Ultra96v2在Zynq SoC FPGA的ARM处理器上运行的自定义Web服务器,因此我意识到如何轻松地利用FPGA作为解决方案来帮助餐馆在COVID期间适应。我再次转向值得信赖的MiniZed,以查看为可通过QR码访问的数字餐厅菜单创建独立解决方案有多么简单。 该项目的骨干是在MiniZed的Zynq芯片的ARM内核上运行的Web服务器。过去,我已经介绍了如何为MiniZed创建自定义Web服务器,但是由于在定制它以满足餐厅的需求方面有一些不同的重点,因此我想在这里再次进行概述。我家乡的一家本地咖啡店在他们的社交媒体上发布了他们正在寻找数字菜单解决方案的信息,因此我决定在Web服务器的主页中使用其菜单和徽标。 我从在Ouija板项目中为MiniZed创建的ext4根文件系统映像开始。由于Web服务器是用Python编写的,因此与Web服务器的静态文件夹所需的Python程序包(Flask和Requests )以及必需的图像文件相比,MiniZed所需的默认initramfs图像需要更多的空间。 后端Python 对于用Python编写的Web服务器的后端,它运行Flask应用程序,该应用程序使用HTML请求来服务来自前端HTML的GET和POST请求。服务器的每个网页都定义为一个函数,概述了如何返回具有所需数据的渲染模板。 首先,使用pip安装Python包Flask和Requests: 然后为Web服务器创建新文件。我选择启用调试选项(app.debug = True),该选项将HTTP请求和结果状态代码输出到串行控制台。 注意,主页被定义为home()函数,而GET和POST请求都只是返回主页的渲染HTML模板。 Web服务器文件结构 如前所述,要使准系统Web服务器运行在FPGA或微控制器之类的设备上,必须满足最低文件结构要求。 调用render_template()方法时,它将在模板目录中查找HTML模板。模板所在的目录也是webserver.py脚本所在的目录。HTML模板文件的名称是传递给render_template()方法的唯一必需参数,而可选参数包括任何要作为关键字参数传递给模板引擎的变量。 另一个所需的目录是静态目录。Flask应用程序在静态目录中提取CSS来获取Web网页模板的格式,JavaScript和图像文件。该图像目录是在咖啡馆的菜单和标识的文件将被放置。 前端模板 有一个默认模板可以用作所有网页的通用基础。默认模板处理诸如基本CSS主题,将出现在每个网页上的页眉和页脚以及列出每个可用页面的导航工具栏之类的事情。 在此模板中,将在每个网页的标题中调用咖啡店的徽标。目前,菜单只有主页,因此home.html是导航栏部分中的唯一选项。 默认HTML模板: 主页模板是显示咖啡店菜单图像文件的位置。可以调用一种简单的CSS样式,使图像自动调整大小到当前窗口的大小,以便在访问该设备的任何设备上看起来都干净整洁。 带有菜单的主页HTML模板: HTML模板完成后,在MiniZed上启动Web服务器: 然后在浏览器中使用MiniZed本地IP来查看网页。我把它放在手机上,因为大多数客户流量来自他们的智能手机。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值