暴力解决AJAX传GB2312编码的字符串
通过js暴力转码,解决项目中ajax只能utf-8的问题,ajax的req只Content-Type : xxxx;charset=UTF-8。爷无语,不管怎么改xhr.setRequestHeader(“Content-Type”,“application/x-www-form-urlencoded;charset=gb2312”),都不给点反应的。
解决方法
整个项目是GB2312编码,后端是c语言,arm 。整个结构大概就是后台管理,前台用户。管理账号少,用的也就是前后不分离的操作非常省事,完全的也七七八八,完美。
但是前台用户量多,请求可能会比较大,准备分离,但是jq也好原生ajax也好,怎么整都是utf-8,成片的乱码。也用了挺多方法,最后找了一个js手动转码的方法。
如果想用上jq的话,本篇最后也提供了想法,大概就是找jq的封装方法,把转编码重写,见下面jq段落。
上连接:https://gitee.com/leaflxd/encodeToGb2312?_from=gitee_search
转码js:
function(){
var json = {...
}
// 自己进连接看
var encodeToGb2312 = function(str)
{
if(typeof(str) === "number")
{
return str;
}
else
{
var strOut="";
for(var i = 0; i < str.length; i++)
{
strOut += "%";
var c = str.charAt(i);
var code = str.charCodeAt(i);
var gcode = json[code.toString(16).toUpperCase()];
if(gcode && gcode.length % 2 !== 0)
{
gcode = "0" + gcode;
}
if(c==" ")
{
strOut += "20";
}
else if(code < 164)
{
var b = str.charCodeAt(i).toString(16);
if(b && b.length % 2 !== 0) b = "0" + b;
strOut += b;
}
else if(gcode)
{
strOut += gcode[0]+gcode[1]+"%"+gcode[2]+gcode[3];
}
else
{
//异常直接打印中文一一一,总得打印点什么233
//unicode 4e00 ; gb2312 d2bb
strOut += "D2%BB";
}
}
}
}
}
xhr js:
document.getElementById("btn2").onclick = function()
{
//alert("a");
type = "POST"
url = "/main/TestCgic";
conttype = "application/x-www-form-urlencoded;charset=gb2312";
v = document.getElementById("t1").value;
data = "pass="+encodeToGb2312(v);
console.log(data);
reqcgic(type, url, conttype, data,
function showdata(value){
document.getElementById("p2").innerText = value;
});
}
......
function reqcgic(type, url, conttype, data, callback)
{
xhr = createXHR();
xhr.open(type, url, true);
xhr.setRequestHeader("Content-Type",conttype);
xhr.onreadystatechange = function()
{
if(xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304) )
{
console.log(xhr);
callback(xhr.responseText);
}
};
xhr.send(data);
}
大概就是这个意思
实际效果:
头部:

请求体:

其他方法
其他方法也看了蛮多
就说一下最多的是方法,两种本质是一样的,一个是js一个是jq
js
- 两个函数先写上
escape
unescape
encodeURIComponent
decodeURIComponent
大体意思是转解码,上面两unicode,下面两utf-8,可以自行尝试下。
decodeURIComponent有一个报错单独拎出来一下,URIError: malformed URI sequence,转义造成的问题。上连接https://blog.csdn.net/chuangxin/article/details/84242109 - 前端:
前面js处使用escape变成Uincode编码,然后套一个encodeURIComponent。
escape是转成Uincode的编码,格式%uxxxx,这里encodeURIComponent这个大概意思就是再转utf-8,也就是我们变成我们请求体里面的东西了,如上图那样。但是因为是%uxxxx,所以请求体里是%25uxxxx,后面接受到的字符串是%uxxxx。见图


这里有两种处理方法,一种直接传到前端,然后unescape显示回来,另一种就是后面处理,将unicode转成GB2312。一般来说第二种,因为有些也不单单是只有网页的,所以编码统一很重要,主要还是看项目。
c语言的转码是#include <iconv.h>,但是我没成功,还是对js下的手。代码如下,上连接https://blog.csdn.net/violet089/article/details/51568667
iconv c
/********************************************************************************************************
** 函数名称: code_convert()
** 函数主题: u转gb2312
** 功能描述:
********************************************************************************************************/
int code_convert(char *inbuf,char *outbuf)
{
iconv_t cd;
int rc;
char **pin = &inbuf;
char **pout = &outbuf;
int inlen = strlen(inbuf);
int outlen = strlen(outbuf);
cd = iconv_open("GB2312","UNICODE//IGNORE");
if(cd == -1)
{
printf("<cd:%d>", cd);
}
/*
* cd 全是-1,iconv_open里面有各种说法
* 我尝试了GB2312,UNICODE//IGNORE,UTF-8,UNICODELITTLE,全是-1,一0难见啊
* 还有可能是库相关版本造成的
* 更新iconv相关函数有两种方法:
* 第一,更新libc库;
* 第二,更新libiconv库;
* 这个么环境原因就不尝试了,相关连接:https://blog.csdn.net/violet089/article/details/51568667
*/
return 0;
memset(outbuf,0,outlen);
iconv(cd,pin,&inlen,pout,&outlen);
printf("<0:%s:%s>", inbuf, outbuf);
iconv_close(cd);
return 0;
}
jq
- 重写jq方法
大体也是jq对ajax进行了封装,里面也是采用了encodeURIComponent进行编码转换,然后自己重写一下这个方法就可以了。
先上连接:连接有点长,上标题:jQuery ajax在GBK编码下表单提交终极解决方案(非二次编码方法)
连接的方法是直接上escape伺候,我这个应该是用那个方法伺候。
见 jquery-1.11.0.js 第9505行。
jQuery.param = function( a, traditional ) {
var prefix,
s = [],
add = function( key, value ) {
// If value is a function, invoke it and return its value
value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
};
............
.......
...
};
疑问
上面jq方法我也就有个疑问,为什么encodeURIComponent用了之后就能正常发呢,正常来说,在没有上面所有操作下,一个中文传到了后面,打印出来就是9个字符,然后变成GB2312中文就是四个乱码+一个?,说明可能还有一次utf-8转码。为什么转码之后就没事了,%为什么不会变成%25。迷惑,俺也不晓得。
jq版解决方法
已经重写完了,直接上代码了
jqOverride.js
//重写jq.param
function buildParams( prefix, obj, traditional, add ) {
var name;
if ( jQuery.isArray( obj ) ) {
// Serialize array item.
jQuery.each( obj, function( i, v ) {
if ( traditional || rbracket.test( prefix ) ) {
// Treat each array item as a scalar.
add( prefix, v );
} else {
// Item is non-scalar (array or object), encode its numeric index.
buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
}
});
} else if ( !traditional && jQuery.type( obj ) === "object" ) {
// Serialize object item.
for ( name in obj ) {
buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
}
} else {
// Serialize scalar item.
add( prefix, obj );
}
}
$.param = function( a, traditional ) {
var prefix,
s = [],
add = function( key, value ) {
// If value is a function, invoke it and return its value
value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
s[ s.length ] = encodeToGb2312( key ) + "=" + encodeToGb2312( value );
};
// Set traditional to true for jQuery <= 1.3.2 behavior.
if ( traditional === undefined ) {
traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
}
// If an array was passed in, assume that it is an array of form elements.
if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
// Serialize the form elements
jQuery.each( a, function() {
add( this.name, this.value );
});
} else {
// If traditional, encode the "old" way (the way 1.3.2 or older
// did it), otherwise encode params recursively.
for ( prefix in a ) {
buildParams( prefix, a[ prefix ], traditional, add );
}
}
// Return the resulting serialization
return s.join( "&" ).replace( /%20/g, "+" );
};
https://www.cnblogs.com/liushui-sky/p/10483248.html
关于URL编码
如上述连接中所述,中文在转成URL编码是三个字符串,通过unicode进行转换。
原文:
8、注意unicode的字符编码和utf-8的存储编码表示是不同的,例如"严"字的Unicode码是4E25,UTF-8编码是E4B8A5,这个7里面解释了的,UTF-8编码不仅考虑了编码,还考虑了存储,E4B8A5是在存储识别编码的基础上塞进了4E25。
4E25的二进制位 0100,1110,0010,0101 中文汉字在utf-8中到底占几个字节,一般是3个字节(原因见第一章),最常见的编码方式是1110xxxx 10xxxxxx 10xxxxxx。组合起来为 1110,0100,1011,1000,1010,0101 =E4B8A5
其中
-
application/x-www-form-urlencoded:需要编码
-
multipart/form-data:并不需要
因为URL编码解决的是单字节和多字节在http传输中冲突而产生的
当我们需要发送一个多字节字符,例如中文的中字,如果直接使用utf-8编码发送,其编码为0xE4B8AD,会使用三个字节传输,分别为0xE4,0xB8,0xAD,当某些中文或者多字节的字符发送时,恰好有一个字节解码为0x26或者0x3D时,这个多字节字符中一个字节将会被接收段解码为=或&符号这中特殊字节,从而将数据从此处断开,产生数据的错误。原文连接https://www.cnblogs.com/k5210202/p/13819449.html
本文介绍如何解决在使用AJAX时只能发送UTF-8编码,无法发送GB2312编码的中文字符的问题。通过JS手动转码和重写jQuery AJAX方法,实现了GB2312编码的传输,避免了乱码。文中还探讨了URL编码、Unicode与UTF-8的区别,并提供了相关代码示例。
735

被折叠的 条评论
为什么被折叠?



