在nodejs中将GBK转UTF

问题

在对接第三方接口时接口返回的响应数据格式为GBK而服务端语言使用的是nodejs
于是常规的方式接收到数据后中文呈现乱码

心路历程

通过网上查找解决方案,最多的就是使用以下方式将GBK转为UTF

// 可以通过该命令`npm install iconv-lite`安装插件,并引入(*已安装可忽略*)
const iconv = require("iconv-lite")
let str = "你好"
let gbkStr = iconv.encode(str, "gbk") // 可以通过encode将字符串转为gbk格式的二进制buffer流
console.log(str,"转为GBK后", gbkStr)
console.log("GBK字符串显示", gbkStr.toString())
let utfStr = iconv.decode(gbkStr, 'gbk') // 然后将二进制buffer流通过decode转换回来
console.log("复原字符串显示", utfStr)
// output
// 你好 转为GBK后 <Buffer c4 e3 ba c3>
// GBK字符串显示 ���
// 复原字符串显示 你好

这个方案很简单但是我遇到了另一个简单的问题

axios.post(TAPI_URL, {
  sign: sign,
  agentAccount: TAPI_ACCOUNT,
  busiBody: data,
}).then((res) => {
  console.log("res.data: ", res.data)
})
// 通过打印可以看出我们在http响应中拿到的数据已经是字符串了
// output
// res.data: {
//   "code": 0,
//   "msg": "���"
// }

那么怎么通过�����ɹ�已经乱码的字符串转换成buffer再解析呢,我又查阅了很多网上的方案还是同上面一样,只要搜索nodejsgbkutf出现的就都是说用iconv.decode(buffer, 'gbk')
怎么样都没找到将已经乱码的字符串转换成buffer

解决问题

于是我转而思考另一个方向,可以在接收响应的时候就直接接收二进制buffer流吗?
果然换了一个方向得以解决了这个问题

axios.post(TAPI_URL, {
  sign: sign,
  agentAccount: TAPI_ACCOUNT,
  busiBody: data,
}, {
  responseType: 'arraybuffer' // 设置响应数据类型为二进制缓存流
}).then((res) => {
  console.log("res.data: ", res.data)
  // 别忘了将转化好后的字符串恢复为json对象
  const data = JSON.parse(iconv.decode(res.data, "gbk")) // 解析gbk字符集
  console.log("data: ", data)
})
// output
// res.data: {
//   "code": 0,
//   "msg": "���"
// }
// data: {
//   "code": 0,
//   "msg": "你好"
// }

思考

通过以上的问题我们发现了两个关键点

  • buffer
  • responseType

buffer

iconv源码

declare module 'iconv-lite' {
  export function decode(buffer: Buffer, encoding: string, options?: Options): string;
  export function encode(content: string, encoding: string, options?: Options): Buffer;
  ...
}

从上面代码可以看出decode并不是直接把乱码字符串传入,而是传入对应字符格式的Buffer类型

Node.js Buffer(缓冲区)
JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。
但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。
在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。

可以再通过学习与使用熟悉该数据类型

responseType

通过对解决问题的思考方向转变后,我通过查看axios源码找到了最终解决的接口
axios源码

export interface AxiosInstance {
  ...
  // post方法中的第三个变量config为AxiosRequestConfig接口格式类型
  post<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
  ...
}
export interface AxiosRequestConfig {
  ...
  // 该类型提供了ResponseType类型的responseType属性
  responseType?: ResponseType;
  ...
}
// ResponseType类型中可使用的参数如下,其中就有arraybuffer数据类型
export type ResponseType = 
  | 'arraybuffer' 
  | 'blob' 
  | 'document' 
  | 'json' 
  | 'text' 
  | 'stream'

查看axios源码我们找到了使响应格式呈buffer格式的接口,通过ResponseType类型的定义还可以发现响应类型的设置还有其他几种类型

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值