【问题标题】:Trying to send a compressed base64 encoded string from JS to AS3 via Websocket. Problem with uncompressing尝试通过 Websocket 将压缩的 base64 编码字符串从 JS 发送到 AS3。解压问题
【发布时间】:2021-01-02 08:31:20
【问题描述】:

您好,祝您 2021 年更快乐、更健康!

我正在基于 Websockets 协议在 JS 客户端和 AS3 服务器之间建立一个小型通信接口。 由于各种原因,我需要对有效负载进行压缩和 base64 编码。 从 AS3 到 JS 一切都是这样工作的(使用 https://github.com/blooddy/blooddy_crypto 处理 Base64 加密/解密):

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 进行通货膨胀解码 (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 收到的字节与 AS3 使用的不同?

欢迎指点!

【问题讨论】:

  • 如果我能解决这样的问题,我会用一些简单的短文本来跟踪和比较 JS 与 AS3 中编码的所有阶段:原始 > encodeURI > compress/deflate > base64 to看看它的发展方向不同。
  • 在 AS3 中执行 ba.uncompress(); 部分之前,跟踪 ba[0]ba[1] 的值是什么?
  • 这似乎是问题所在。 ba 可以追溯到: 120,156,203,72,205,201,201,87,53,50,40,207,47,202,73,1,0,33,27,4,196 这是 JS 中的 pako.defalte 生成的: Uint8Array(21) [ 120, 156, 203 , 72, 205, 201, 201, 87, 53, 50, 40,207,47,202,73,1,0,33,27,4,196 ] 格式好像和 AS3 ByteArray 有点不一样?
  • 正确的 Zlib 标头确实以 120 开头,后跟 156,因此两个系统(AS3 和 JS)都显示正确的 Zlib 数据编号。在这一点上它应该工作......但不知何故,你违反了宇宙法则。我稍后会为您检查...
  • 好的。我发现了错误。相当愚蠢的一个,因为它大多是。 uint8Array 当然需要转换为二进制字符串...请参阅上面我编辑的帖子中的详细信息。

标签: javascript arrays actionscript-3


【解决方案1】:

这是解决方案 - 当然是一个愚蠢的小疏忽;)

在 JS 的 encode 函数中,Uint8Array 需要先转换成 BinaryString 才能进行 Base64 编码:

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;
}

那么罗斯威尔一切顺利。

【讨论】:

    【解决方案2】:

    如果您的 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 端口。

    获取 as3zlibhttps://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
    }
    

    【讨论】:

    • 谢谢。稍后我会研究你的建议。是的,应该加了,是AIR项目。
    • 你好 VC.One,我试过 ba.uncompress.apply(ba, ["deflate"]); 但它会产生同样的错误。我还尝试实现您的代码示例decoded_BA = zlibdecomp.uncompress( ba ); ,但链接的 as3zlib 库没有按照您的示例进行结构化。 Zlib 类不存在,所以我无法实例化zlibdecomp = new Zlib; 有什么想法吗?非常感谢!
    • 我一直在深入挖掘项目中使用的文件。 Download the ZIP(右键单击并保存)并将所有文件放在与您的 AS3 相同的位置。您仍然需要 com/wirelust/AS3Zlib 文件夹,因为这些 .as 文件引用了该库。
    • 所以。我尝试了 Zlib,但它也会生成“未知压缩方法”错误。正如我在上面的评论中提到的那样,我将不得不研究 pako 生成的 Bytearray 格式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-09
    • 2021-11-30
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    相关资源
    最近更新 更多