NetSuite接口开发之JSON源数据发送实现gzip压缩

NetSuite如何发送大容量数据到第三方的专业系统? 通过压缩数据实现突破默认HTTP Post的数据量上限限制

有什么用/怎么用

当需要一次发送大量的数据到第三方系统时, 或者第三方系统post进NetSuite大容量(size)的数据时,

将需要发送的数据ajax post中的body payload 进行gzip压缩(或解压缩)

image-20260415184103239

相关内容

实现方法

GZIP压缩

压缩级别: 4

字符串编码方式: UTF8

最后选用gzip NetSuite系统算法

测试用例20260415, 测试单据: IA2339,

压缩前:

1
[{"type":1,"internalid":"11272","locationInfos":[{"locationid":"1","storageLocInfos":[{"storagelocid":"20","goodInventoryInfos":[{"inventoryInfos":[{"inventorycount":"123","inventorynumber":"cea"}]}]}]}]}]

NetSuite压缩后:

1
H4sIAAAAAAAA/33OQQrCQAyF4bu8dRfOuBDmBgVvUFyM01gGaiLTVCildzfVaneS3Z8PkmaGTg9CcBUyKxWOfW4R4Jw/eVToJUXNwjXfZEBo5l/5MCODSokdnSXtaGtm38wfzHUibc1PYttNO81/UpKRdT3jj1gf3DKP9ysV64kilst3XsR9VMbNAAAA

网站压缩后: (比对测试网址: Gzip/Deflate 压缩 - 在线免费工具 | TingYu Tools)

1
H4sIAAAAAAAAA33OQQrCQAyF4bu8dRfOuBDmBgVvUFyM01gGaiLTVCildzfVaneS3Z8PkmaGTg9CcBUyKxWOfW4R4Jw/eVToJUXNwjXfZEBo5l/5MCODSokdnSXtaGtm38wfzHUibc1PYttNO81/UpKRdT3jj1gf3DKP9ysV64kilst3XsR9VMbNAAAA

备注: 多次测试发现并核实NetSuite生产的压缩数据(不管那个压缩级别)都是会与网站测试差一个字符: 第13个字符, NetSuite总是输出 /, 网站总是输出A, 其他都一致; 我觉得这应该不影响解压, 因为用NetSuite压缩过的数据可以用测试网站解压缩出正确的结果(结果一致).

压缩级别说明

​ ● 1-3:快速压缩,较低压缩率

​ ● 4-6:平衡速度和压缩率(推荐)

​ ● 7-9:最佳压缩,速度较慢

应用场景

​ ● HTTP 响应压缩(Gzip)

​ ● 文件压缩和传输

​ ● 减少 API 响应体积

​ ● 数据存储优化

注意事项

​ ● 压缩数据以 Base64 格式输出,便于传输

​ ● 随机数据或已压缩数据可能无法进一步压缩

​ ● 重复内容越多,压缩效果越好

测试完成gzip压缩用于发送库存变动的payload数据

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//......

var objTxtFile = file.create({
fileType: 'PLAINTEXT',
name: 'file.txt',
encoding: file.Encoding.UTF8,
contents: JSON.stringify(arrInvData)
});
var gzippedFile = compress.gzip({
file: objTxtFile,
level: 4
});
var strGzipText = gzippedFile.getContents();

let objBody = {
"messageId": new Date().getTime().toString(),
"route": "inventoryUpdate",
"payload": strGzipText
};

//......

pako.js工具压缩探讨

1
https://github.com/nodeca/pako
1
2
3
const test = { my: 'super', puper: [456, 567], awesome: 'pako' };

const compressed = pako.deflate(JSON.stringify(test));

由于NetSuite的server端, 无法将compressed的数据转化成string,

在client端, 可以使用btoa, windows.btoa来encode转化成字符; 而server端没有这个build-in函数

有一些第三方的btoa的实现方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//private property
let _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
private method for UTF-8 encoding
function _utf8_encode (string) {
if (!string) return '';
string = string.toString().replace(/\r\n/g,"\n");
let utftext = "";
for (let n = 0; n < string.length; n++) {
let c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}

}
return utftext;
}

// private method for UTF-8 decoding
function _utf8_decode (utftext) {
let string = "";
let i = 0;
let c = 0;
let c1 = 0;
let c2 = 0;
let c3 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}

// public method for encoding
const encode = (input) => {
let output = "";
let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
let i = 0;
input = _utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
_keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
_keyStr.charAt(enc3) + _keyStr.charAt(enc4);
}
return output;
}

// public method for decoding
const decode = (input) => {
let output = "";
let chr1, chr2, chr3;
let enc1, enc2, enc3, enc4;
let i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = _keyStr.indexOf(input.charAt(i++));
enc2 = _keyStr.indexOf(input.charAt(i++));
enc3 = _keyStr.indexOf(input.charAt(i++));
enc4 = _keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = _utf8_decode(output);
return output;
}

个性化需求沟通 扫客服加V加群: