Because the company needs to use protobuf, then there is this dent record
What is a protobuf?
The official explanation:
Protocol buffers are a flexible, efficient, automated mechanism for serializing structured data — THINK XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages. You can even update your data structure without breaking deployed programs that are compiled against the “old” format.
My English is not good.
Protocol buffers are a flexible, efficient automation mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You can define the structure of the data once, and then you can easily write structured data to various data streams using special source code and read and read the data in various languages. You can even update your data structures without interrupting deployed programs compiled according to the “old” format.
Features:
- More simple
- It’s 3 to 10 times smaller
- It’s 20 to 100 times faster
- Not too vague
- Generate data access classes that are easier to use programmatically
code
I wrote a demo address on Github. If you need it, you can download it and run it to understand. PS: If you feel useful, please give me a little star (pen core ~)
use
Illegal token ‘<‘ (/demo.proto, illegal token ‘<‘ (/demo.proto, Line 1) CHECKED the official website issue, the general idea should be that the proto file has too many characters, but I checked the proTO file and did not find many ‘<‘, what should I do? Finally, I gave up using the third party. Use the official method.
Download the Protobuf compiler
Github also provides a zip package that you can download yourself (the latest version is v3.6.0) to compile proto into JS files
Configuring environment Variables
The only difference between Mac and Window commands is that you need to change protoc to protoc. Exe if you need to add environment variables to configure environment for reference in this article
Write proto files
In order to ensure consistency, the following is a test proTO written to me by the background. The background of our company is Java
syntax = "proto2"; // Protobuf version option java_package ="com.test.protobuf";
option java_outer_classname = "PersonMessage"; message Person { required int32 id = 1; optional string name = 2; optional string email = 3; repeated string list = 4; extensions 100 to 1000; } message PersonTree {optional string ID = 1; optional string title = 2; repeated PersonTree childs = 3; } extend Person { optional int32 count = 101; optional int32 likes_cnt= 102; } message PersonEx { optional int32 id = 1; extend Person { optional int32 px = 103; optional int32 py= 104; } optional Person p = 2; }Copy the code
Build a project directory using vue-CLI
npm install -g vue-cli
vue init webpack my-project
cd my-project
npm install
npm run dev
Copy the code
NPM install axios element- UI Google -protobuf –save
Compile proto to JS
Protoc. Exe –js_out=import_style=commonjs,binary:.awesome. Proto
- Will generate a
awesome_pb.js
file - Click to view
awesome_pb.js
And you can actually see that there’s a good way to generate. Just introduce a JS call to the page
Later we’ll import this file to the page, but you can also consider global references
test
Local test
Import messages from ‘./awesome_pb.js’
methods: {
protobufferTest () {
var message = new messages.Person() // Call the Person object to instantiate
/ / assignment
message.setId(23)
message.setName('asd')
/ / the serialization
var bytes = message.serializeBinary()
console.log(bytes) // Uint8Array(7) [8, 23, 18, 3, 97, 115, 100]
// deserialize
var message2 = messages.Person.deserializeBinary(bytes)
console.log(message2) // proto.PersonTree {wrappers_: null, messageId_: undefined, arrayIndexOffset_: -1, array: Array(3), pivot_: 1.7976931348623157 e+308,... }}}Copy the code
At this point, the local tests are done, and there’s nothing wrong with them.
Front and rear end joint test
In front of a pit
The forward and backward transfer was using FormData, and then the tragic thing happened. The background doesn’t parse. I checked the data [8, 23, 18, 3, 97, 115, 100] and it did pass. It was later checked that the reason should have been parsed into a string, and then the value changed. So it doesn’t work out. The fromCharCode() method is then used to edit it into a string and pass it to the background. The charCodeAt() value is used.
ProtobufferTest () {this method is deprecatedvar message = new messages.Person() // Call the Person object to instantiate
/ / assignment
message.setId(23)
message.setName('asd')
/ / the serialization
var bytes = message.serializeBinary()
console.log(bytes) // Uint8Array(7) [8, 23, 18, 3, 97, 115, 100]
var tests = ' '
for (let index = 0; index < bytes.length; index++) {
tests += String.fromCharCode(bytes[index])
}
console.log(tests) // asd
/ / in the FormData
let uploadDatas = new FormData()
uploadDatas.append('protobuf', tests)
// Use axios to transmit to the background
this.axios.post('/test', uploadDatas)
.then(function (response) {
// Convert the returned string to an array
console.log(response.data.split(' ')) / / / "↵", ""," 3 ", "2", ""," ", "a", "s", "d", "f"]
let str = response.data.split(' ')
let toChar = []
for (let index = 0; index < str.length; index++) {
toChar.push(str[index].charCodeAt())
}
console.log(toChar) // [10, 2, 51, 50, 18, 4, 97, 115, 100, 102]
// The background returns the value from PersonTree, so call PersonTree to deserialize it
var message2 = messages.PersonTree.deserializeBinary(toChar)
console.log(message2) // proto.PersonTree {wrappers_: null, messageId_: undefined, arrayIndexOffset_: -1, array: Array(3), pivot_: 1.7976931348623157 e+308,... }
// Get the id of the PersonTree
console.log(message2.getId()) / / 32
})
.catch(function (error) {
console.log(error)
})
}
Copy the code
The above methods may have security risks. Back end value Because FormData supports two ways to transfer the string and blob so deposited the bytes in a blob of front end to get the data changes on the default transport axios axios. Defaults. ResponseType = ‘arraybuffer’ Change the JS code above to the following
protobufferTest () {
var message = new messages.Person()
message.setId(23)
message.setName('asd')
var bytes = message.serializeBinary()
console.log(bytes)
let uploadDatas = new FormData()
var blob = new Blob([bytes], {type: 'application/octet-stream'})
uploadDatas.append('protobuf', blob)
this.axios.post('/test', uploadDatas)
.then(function (response) {
console.log(response)
var message2 = messages.PersonTree.deserializeBinary(response.data)
console.log(message2.getId())
})
.catch(function (error) {
console.log(error)
})
// console.log(bytes)
}
Copy the code
So far before and after the joint investigation is completed
Reference documentation
Use Google-Protobuf in front end, back end and game
How does the javascript front end use Google-Protobuf