Highcharts 官方提供的导出服务器(https://export.highcharts.com.cn) 默认只支持 UTF-8 编码,如果从 GBK 页面提交导出请求,导出的结果是包含乱码的图片,这是很常见的编码问题。
在不能改变页面编码的情况下,解决办法有两种:
- 修改导出服务器源码(源码可以到 node-export-server 下载,详见 教程)使其能够支持 GBK 编码
- 另外一种方法是将发送到导出服务器的数据改成 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 之后引入插件文件即可。


