GBK 页面导出 Highcharts 图表乱码解决办法

Highcharts 官方提供的导出服务器(https://export.highcharts.com.cn) 默认只支持 UTF-8 编码,如果从 GBK 页面提交导出请求,导出的结果是包含乱码的图片,这是很常见的编码问题。

在不能改变页面编码的情况下,解决办法有两种:

  1. 修改导出服务器源码(源码可以到 node-export-server 下载,详见 教程)使其能够支持 GBK 编码
  2. 另外一种方法是将发送到导出服务器的数据改成 UTF-8。

第一种方法相对比较麻烦,这里我们就简单说说第二种方法的具体实现方法。

主流浏览器

对于主流浏览器( IE8 以上),我们可以在 exporting.formAttributes 中加入编码属性即可,代码是:

exporting: {
  url: 'https://export.highcharts.com.cn',
  formAttributes: { 
    // 在导出的 formAttributes 中设置表单的编码
    "acceptCharset": "UTF-8"
  }
}

formAttributes 的作用是指定在调用 Highcharts.post 函数时创建的表单的额外属性,上面的代码其实就相当于

<form accept-charset="UTF-8">

至于 Highcharts.post 为什么会创建表单,可以自行阅读源码。

IE

对于 低版本 IE 来说(IE8 以下),他完全不认 form 的 accept-charset 属性,他提交表单的编码是按照页面的 meta 指定的字符集。

可喜的是 IE 浏览器中的 document.charset 是可读可写的,并且在改变它时页面是不会用新的编码重新渲染页面。

结合 Highcharts,我们可以在 Highcharts.post 中做处理,即在提交数据之前将页面的编码设置为 UTF-8,并在导出结束后恢复原始编码,具体的实现代码如下:

H.post = function(url, data, formAttributes) {
    var name,
        form;

    if (!formAttributes) {
        formAttributes = {}
    }
    // 增加表单属性
    formAttributes.acceptCharset = "UTF-8";

    form = createElement('form', merge({
        method: 'post',
        action: url,
        enctype: 'multipart/form-data'
    }, formAttributes), {
        display: 'none'
    }, document.body);


    for (name in data) {
        createElement('input', {
            type: 'hidden',
            name: name,
            value: data[name]
        }, null, form);
    }

    // 1. 修改网页编码
    document.charset = 'UTF-8';

    form.submit();

    // clean up
    discardElement(form);

    // 2. 恢复原始编码
    document.charset = originCharset;
}

最后,我们将上述两个解决方法整合在一起,并编写成一个 Highcharts 插件,插件代码如下:

(function(H) {
    var DEFAULT_VERSION = "8.0",
        ua = navigator.userAgent.toLowerCase(),
        isIE = ua.indexOf("msie") > -1,
        safariVersion;
    if (isIE) {
        safariVersion = ua.match(/msie ([\d.]+)/)[1];
    }

    if (safariVersion <= DEFAULT_VERSION) {
        var discardElement = H.discardElement,
            createElement = H.createElement,
            merge = H.merge,
            // 保存页面的原始编码
            originCharset = document.charset;

        H.post = function(url, data, formAttributes) {
            var name,
                form;

            if (!formAttributes) {
                formAttributes = {}
            }
            // 增加表单属性
            formAttributes.acceptCharset = "UTF-8";

            form = createElement('form', merge({
                method: 'post',
                action: url,
                enctype: 'multipart/form-data'
            }, formAttributes), {
                display: 'none'
            }, document.body);

            for (name in data) {
                createElement('input', {
                    type: 'hidden',
                    name: name,
                    value: data[name]
                }, null, form);
            }

            // 1. 修改网页编码
            document.charset = 'UTF-8';

            form.submit();

            // clean up
            discardElement(form);

            // 2. 恢复原始编码
            document.charset = originCharset;
        }
    }
}(Highcharts));

插件的使用方法很简单,只需要在 highcharts.js 之后引入插件文件即可。

资源文件下载

https://data.jianshukeji.com/upload/20170907/anwvcb.zip

分享到评论