web前端 js环境 使用 protobuf google-protobuf

google-protobuf 官网地址 https://developers.google.com/protocol-buffers/

 

  网上有些封装过后支持前端使用的 google-protobu f库,比如 protobufjs ,不过看了下不太喜欢...

  感觉就还是使用 google-protobuf 官网提供的比较舒心!

 

一、安装protoc编译器

  官网下载地址:https://github.com/protocolbuffers/protobuf/releases

  打开网址:

web前端 js环境 使用 protobuf google-protobuf

 

  下拉:

web前端 js环境 使用 protobuf google-protobuf

 

  本来打算直接下载  protobuf-all-3.14.0.zip  压缩包,毕竟谁在乎占用那几M大小嘛...安装了,能编译成对应的JS、GO等等就比较好...

  结果不行:

web前端 js环境 使用 protobuf google-protobufweb前端 js环境 使用 protobuf google-protobuf

  编译是用的一个 protoc.exe 可执行文件,这里面就没有。

 

  要下载对应系统的压缩包!

 

  下载 protoc-3.14.0-win64.zip (对应自己的系统),解压,进入 bin 文件夹就发现 protoc.exe 文件了:

web前端 js环境 使用 protobuf google-protobuf

 

  现在就可以用这个 protoc.exe 编译文件了。可以每次进到这个目录执行,也可以加入环境变量,就可以在自己的项目编辑器里面直接使用。

 

二、根据 *.proto 文件,编译为对应语言的文件

 直接在目录位置输入 cmd 然后回车 打开在当前目录的命令行工具

web前端 js环境 使用 protobuf google-protobufweb前端 js环境 使用 protobuf google-protobuf

 

 输入编译命令: 

  protoc *.proto --js_out=import_style=commonjs,binary:../pb     说明:     *.proto        选中当前目录的所有后缀为 .proto 的文件(也可以具体的某一个文件)。如果没有进到 *.proto 文件所在的目录,也可以加上路劲:../path1/*.proto 这种。但是如果proto之间有相互引用,就不要加路劲了,引用会报错。     --js_out      编译目标为 js 文件     commonjs      编译出来的 js 文件,按照 commonjs 导入使用     binary:./proto-js  编译的输出目录,就是个相对路径。例如一个点:binary:. 直接编译到当前目录。文件多的时候建一个文件夹(提前建好,不然报错)来放比较安逸   我放入了一些测试文件、建了两文件夹: web前端 js环境 使用 protobuf google-protobufweb前端 js环境 使用 protobuf google-protobuf       只要没报错就编译完成了:   web前端 js环境 使用 protobuf google-protobufweb前端 js环境 使用 protobuf google-protobuf   查看结果: web前端 js环境 使用 protobuf google-protobufweb前端 js环境 使用 protobuf google-protobuf

 

三、导入使用

  按照前面的 commonjs 规范,使用 require 导入:

  web前端 js环境 使用 protobuf google-protobuf

  (proto源文件可能在编辑器里会飘红报错,不用管它...)

  嗯...使用前先:

    npm i google-protobuf

  看一下都有些啥:

web前端 js环境 使用 protobuf google-protobuf

  

  可以看到导入的是一个对象,里面包含了对应 .proto 文件所定义的数据结构。它们都挂载有相同的方法,可以看编译出来的js文件:

web前端 js环境 使用 protobuf google-protobufweb前端 js环境 使用 protobuf google-protobuf

 

  解密数据:deserializeBinary 内部调用的 deserializeBinaryFromReader 方法

  加密数据:serializeBinary 内部调用的 serializeBinaryToWriter 方法

 

  主要目标:

  1. 创建符合 protobuf 的对象,加密,以便传输。
  2. 解密获取的 protobuf  压缩的数据,解析为 js 对象。

  具体例子:

let proto = require("../pb/conn.int_pb");

const protoObj = new proto.Image()//以 new 的方式创建
console.log(protoObj)//输出一个对象 可以看到有一个array属性 array: [] 其实所有的属性值就会放里面,没设置时是空的

//设置对应的属性 (自己确定好属性值的类型)
protoObj.setId('123')
protoObj.setWidth(88)
protoObj.setUrl('123')
console.log(protoObj)//可以看到设置的值 array: [ '123', 88, 88, '123' ]

const protoData = protoObj.serializeBinary()//加密
console.log(protoData)//一串Uint8Array数组值 protobuf 加密过后都是  Uint8Array 类型的数据

const newProtoObj = proto.Image.deserializeBinary(protoData)//解密 必须以对应的数据结构调用方法 传入数据
console.log(newProtoObj)//和 protoObj 数据就一样了 

console.log(newProtoObj.getId())// "123"
console.log(newProtoObj.getWidth())// 88
console.log(newProtoObj.getHeight())// 0 存在的属性 但是前面没有赋值
console.log(newProtoObj.getUrl())// "123"

console.log(newProtoObj.getThumbnailUrl())// "" 存在 但是前面没有赋值 是个空串
// console.log(newProtoObj.getTThumbnailUrl())//不存在的属性 报错 TypeError: newProtoObj.getTThumbnailUrl is not a function

//不存在的属性都会报错,存在的属性都会有对应的默认值
//可以看出来,默认是每个属性都有对应的 get、set方法

// 设置属性好像没有简便方法,我看了看编译出来的js文件,我没瞅见,但是获取有一个,就是 toObject const jsObj = newProtoObj.toObject()//其实就是调用了一遍get方法 //会输出包含所有属性的一个js对象,没有设置的值就是默认值 console.log(jsObj)//直接输出jsObj { id: '123', width: 88, height: 0, url: '123', thumbnailUrl: '' } // 自己写一个设置的方法 function formatSetStruct(structType, structData) {//传入需要的结构类型和对应数据 const newStruct = new proto[structType](); for (let key in structData) {//遍历设置一遍就好 if (Object.hasOwnProperty.call(structData, key)) { let setKey = "set" + key; newStruct[setKey](structData[key]); } } return newStruct.serializeBinary();//直接返回加密的数据 } const testFormat = formatSetStruct('Image', { Id : '123123adas', //string Width : 123, //int32 Height : 67, //int32 Url : '地址', //string ThumbnailUrl : '缩略图地址', //string }) const testJsObj = proto.Image.deserializeBinary(testFormat).toObject() console.log(testJsObj) // { // id: '123123adas', // width: 123, // height: 67, // url: '地址', // thumbnailUrl: '缩略图地址' // } //但是有些特殊情况, proto里面设置的 userIds repeated string 到了js这边 就是 UserIdsList 了 // userIds 属性映射为了 UserIdsList 需要自己处理

 

    OK!

 

上一篇:通过JS逆向ProtoBuf 反反爬思路分享


下一篇:Protocol Buffer入门