需要在浏览器端实现对字符进行GB2312
,GBK
,GB18030
编码解码,搜索如何解决本问题时
搜索到iconv-lite,一个纯JS字符编码转换工具。
文档中表示在浏览器端可以通过browserify
或者webpack
使用。
安装之后,在页面import
后,devServer
编译时报错!
主要是以下两种错误:
第一个 Can't resolve 'buffer'
对于这个错误,是因为需要依赖buffer
,但是项目中没有。安装buffer
即可
npm install -D buffer
安装之后再编译,这个错就没有了
第二个 Cannot parse JSON: Unexpected token ";"
这个错误是因为通过
babel-loader
解析iconv-lit
中的json
文件时出现了无法解析的错误。显然,
json
文件不应该由babel-loader
来解析检查
webpack.config.js
文件发现了如下配置
{
test: /\.jsx?/i,
use: ['babel-loader'],
},
由于此配置,使.json
后缀文件匹配上了/\.jsx?/i
正则,导致json
文件被babel-loader
解析,并报了错。
改善一下正则即可。
改正为只有以.js
或.jsx
为结尾的文件,才使用babel-loader
{
test: /\.jsx?$/i,
use: ['babel-loader'],
},
改正之后再重新运行run server
不报错啦!(*^▽^*)
iconv-lite如何使用呢?
直接看文档中的例子就可以了,可以将require
方式改为import
方式引入
import iconv from 'iconv-lite';
// Convert from an encoded buffer to a js string.
const str = iconv.decode(Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f]), 'GB2312');
// Convert from a js string to an encoded buffer.
const buf = iconv.encode("Sample input string", 'GB2312');
可以用啦(✧◡✧)
另外,在知乎中看到这样一篇文章,使用hack的方式获取编码
https://zhuanlan.zhihu.com/p/35537480
简单测试了一下,一般的文字是可以得到正确编码的,但是对于个别文字会得到意想不到的结果。
比如瞭
,url中编码后的结果是 %B2t
。这个t是什么鬼我实在是无法理解,而且,我改变accept-charset
为GBK
或者GB18030
后,对于这个字的编码都没有改变。我怀疑这种方式无法区分这三种编码,可能是因为这三种编码是向下兼容的吧 ⊙(・◇・)?
因此,我觉得这个方式应该是有点问题的。
这个hack方式的核心在于两点
第一
form
表单的accept-charset
属性,可以指定文本编码方式。设置input
的value
后,通过get
方式提交表单,可以在url
中的参数部分(也就是?
后面)得到编码后的结果。
第二
由于form
表单提交会刷新当前页面,所以创建一个隐藏的iframe
,指定iframe
的name
属性。然后设置form
表单的target
属性与iframe
的name
一致。通过这种方式指定form
提交到隐藏的iframe
中,这样刷新的就是iframe
,而不是当前页面。
最后通过iframe.contentWindow.location.href
获取到iframe
的url
即可。
简单记录一下代码:
html部分
<iframe style={{ display: 'none' }} id="hiddenFrame" name="encode" src="about:blank" />
<div style={{ display: 'none' }}>
<form method="get" acceptCharset="gb18030" target="encode">
<input id="hiddenInput" name="input" />
<input type="submit" value="submit" onClick={onSubmitClick} />
</form>
</div>
js部分
function getUrlGBCode(data: string) {
const form = document.getElementsByTagName('form')[0];
const iframe = document.getElementsByTagName('iframe')[0];
if (form) {
form.acceptCharset = 'gb2312';
const input = document.getElementById('hiddenInput') as HTMLInputElement;
input.value = data;
form.submit();
setTimeout(() => {
const url = iframe.contentWindow.location.href;
console.log('xixi', url);
}, 100);
}
}
2023-10-19