尝试通过 Websocket 将压缩的 base64 编码字符串从 JS 发送到 AS3。解压有问题
Trying to send a compressed base64 encoded string from JS to AS3 via Websocket. Problem with uncompressing
你好,祝 2021 年快乐健康!
我正在基于 Websockets 协议在 JS 客户端和 AS3 服务器之间建立一个小型通信接口。
由于各种原因,我需要对有效载荷进行压缩和 base64 编码。
从 AS3 到 JS 一切都像这样工作(使用 https://github.com/blooddy/blooddy_crypto 来处理 Base64 en/decryption ):
function encodeMessage(message:String):String{
var rawData:ByteArray=new ByteArray()
rawData.writeUTFBytes( encodeURIComponent(message) );
rawData.compress();
var b64 = Base64.encode(rawData);
return b64;
};
在 JS 中使用 pako 解码 inflation (https://github.com/nodeca/pako):
decodePayload(payload){
let rawfile = (atob(payload));
var bytes = [];
for (var fileidx = 0; fileidx < rawfile.length; fileidx++) {
var abyte = rawfile.charCodeAt(fileidx) & 0xff;
bytes.push(abyte);
}
var plain = pako.inflate(bytes);
var enc = "";
for (var i = 0; i < plain.length; i++) {
enc += String.fromCharCode(plain[i]);
}
return decodeURIComponent(enc);
}
现在另一个方向会产生一些问题:
在 JS 中我使用:
encodeMessage(message){
let enc = encodeURIComponent(message)
let zlib = pako.deflate(enc)
let b64 = btoa(zlib);
return b64;
}
但后来我 运行 陷入了 AS3 方面的问题:
function decodePayload(payload:String){
var ba:ByteArray = Base64.decode(payload);
//this is where the error happens
ba.uncompress();
}
错误是“错误:错误 #2058:解压缩数据时出错。”
我怀疑我从 pako.deflate 收到的 bytearry 与 AS3 使用的不同?
欢迎指点!
如果您的 AS3 代码只用在 SWF 文件中,或者您有一个 AIR 项目,这并不明显。
- 如果制作 AIR 项目:
尝试使用 uncompress.apply
...(代码尚未测试)。
//# this is where the error happens
//ba.uncompress();
//# try this..
ba.uncompress.apply(ba, ["deflate"]);
- 如果制作 SWF 项目:
当我需要在浏览器上的 SWF 运行 中使用 Deflate 算法时,我使用了 Zlib 的端口。
在以下位置获取 as3zlib:https://github.com/BenV/as3zlib(是 Java 的 Zlib 端口)。
注意:虽然在 JS 中最好创建局部变量而不是全局变量,这是 JavaScript 的一个怪癖
实际上在大多数类 C 语言(Java、C#、AS3 等)中,这是相反的,全局变量比每次函数都不断地创建局部变量 vars 更便宜被调用。
这是一个用法示例:
//# import Zlib Class
import Zlib;
//# setup global vars
var zlibdecomp :Zlib;
var ba :ByteArray = new ByteArray;
var decoded_BA :ByteArray = new ByteArray;
//# try Deflate algo...
function decodePayload(payload:String)
{
zlibdecomp = new Zlib;
ba.clear(); //in case it already has data from a prev decode
//# all code below can be done in this one line
//ba = zlibdecomp.uncompress( Base64.decode(payload) );
ba = Base64.decode(payload);
//# this is where the error happens...
//ba.uncompress();
//# try this...
decoded_BA = zlibdecomp.uncompress( ba ); //inflate to original big from small/compressed
//ba = decoded_BA; //if this way of updating is needed
}
这是解决方案 - 当然是一个愚蠢的小疏忽 ;)
在JS的encode函数中,Uint8Array在进行Base64编码之前需要转换成BinaryString:
function encodeMessage(message){
let enc = encodeURIComponent(message);
let zlib = pako.deflate(enc);
let binstring = convertUint8ArrayToBinaryString(zlib);
let b64 = btoa(binstring);
return b64;
};
function convertUint8ArrayToBinaryString(u8Array) {
var i, len = u8Array.length, b_str = "";
for (i=0; i<len; i++) {
b_str += String.fromCharCode(u8Array[i]);
}
return b_str;
}
那么罗斯威尔就一切安好
你好,祝 2021 年快乐健康!
我正在基于 Websockets 协议在 JS 客户端和 AS3 服务器之间建立一个小型通信接口。 由于各种原因,我需要对有效载荷进行压缩和 base64 编码。 从 AS3 到 JS 一切都像这样工作(使用 https://github.com/blooddy/blooddy_crypto 来处理 Base64 en/decryption ):
function encodeMessage(message:String):String{
var rawData:ByteArray=new ByteArray()
rawData.writeUTFBytes( encodeURIComponent(message) );
rawData.compress();
var b64 = Base64.encode(rawData);
return b64;
};
在 JS 中使用 pako 解码 inflation (https://github.com/nodeca/pako):
decodePayload(payload){
let rawfile = (atob(payload));
var bytes = [];
for (var fileidx = 0; fileidx < rawfile.length; fileidx++) {
var abyte = rawfile.charCodeAt(fileidx) & 0xff;
bytes.push(abyte);
}
var plain = pako.inflate(bytes);
var enc = "";
for (var i = 0; i < plain.length; i++) {
enc += String.fromCharCode(plain[i]);
}
return decodeURIComponent(enc);
}
现在另一个方向会产生一些问题: 在 JS 中我使用:
encodeMessage(message){
let enc = encodeURIComponent(message)
let zlib = pako.deflate(enc)
let b64 = btoa(zlib);
return b64;
}
但后来我 运行 陷入了 AS3 方面的问题:
function decodePayload(payload:String){
var ba:ByteArray = Base64.decode(payload);
//this is where the error happens
ba.uncompress();
}
错误是“错误:错误 #2058:解压缩数据时出错。” 我怀疑我从 pako.deflate 收到的 bytearry 与 AS3 使用的不同?
欢迎指点!
如果您的 AS3 代码只用在 SWF 文件中,或者您有一个 AIR 项目,这并不明显。
- 如果制作 AIR 项目:
尝试使用 uncompress.apply
...(代码尚未测试)。
//# this is where the error happens
//ba.uncompress();
//# try this..
ba.uncompress.apply(ba, ["deflate"]);
- 如果制作 SWF 项目:
当我需要在浏览器上的 SWF 运行 中使用 Deflate 算法时,我使用了 Zlib 的端口。
在以下位置获取 as3zlib:https://github.com/BenV/as3zlib(是 Java 的 Zlib 端口)。
注意:虽然在 JS 中最好创建局部变量而不是全局变量,这是 JavaScript 的一个怪癖 实际上在大多数类 C 语言(Java、C#、AS3 等)中,这是相反的,全局变量比每次函数都不断地创建局部变量 vars 更便宜被调用。
这是一个用法示例:
//# import Zlib Class
import Zlib;
//# setup global vars
var zlibdecomp :Zlib;
var ba :ByteArray = new ByteArray;
var decoded_BA :ByteArray = new ByteArray;
//# try Deflate algo...
function decodePayload(payload:String)
{
zlibdecomp = new Zlib;
ba.clear(); //in case it already has data from a prev decode
//# all code below can be done in this one line
//ba = zlibdecomp.uncompress( Base64.decode(payload) );
ba = Base64.decode(payload);
//# this is where the error happens...
//ba.uncompress();
//# try this...
decoded_BA = zlibdecomp.uncompress( ba ); //inflate to original big from small/compressed
//ba = decoded_BA; //if this way of updating is needed
}
这是解决方案 - 当然是一个愚蠢的小疏忽 ;)
在JS的encode函数中,Uint8Array在进行Base64编码之前需要转换成BinaryString:
function encodeMessage(message){
let enc = encodeURIComponent(message);
let zlib = pako.deflate(enc);
let binstring = convertUint8ArrayToBinaryString(zlib);
let b64 = btoa(binstring);
return b64;
};
function convertUint8ArrayToBinaryString(u8Array) {
var i, len = u8Array.length, b_str = "";
for (i=0; i<len; i++) {
b_str += String.fromCharCode(u8Array[i]);
}
return b_str;
}
那么罗斯威尔就一切安好