Google Protocol Buffers 簡稱 Protobuf,它提供了一種靈活、高效、自動序列化結構數據的機制,能夠聯想 XML,可是比 XML 更小、更快、更簡單。僅須要自定義一次你所需的數據格式,而後用戶就可使用 Protobuf 編譯器自動生成各類語言的源碼,方便的讀寫用戶自定義的格式化的數據。與語言無關,與平臺無關,還能夠在不破壞原數據格式的基礎上,依據老的數據格式,更新現有的數據格式。前端
先後端都是以二進制形式進行交互信息。先後端定義proto後綴的文件,以此文件來當文檔來進行溝通。java
如下爲protobuf文件的demo,test.proto,文件的結構確實簡單明瞭。node
enum FOO { BAR = 1; } message Test { required float num = 1; required string payload = 2; optional string payloads = 3; } message AnotherOne { repeated FOO list = 1; }
後端以node爲例子:
安裝bufferhelper以及protocol-buffers進行解析protobuf文件ios
npm install bufferhelper npm install protocol-buffers
前端須要安裝解析protobuf的環境。
mac使用brew安裝protobuf環境。此操做須要先安裝Homebrew環境。具體的Homebrew的安裝自行搜索。
windows的前端環境安裝有點不同,自行搜索。npm
brew install protobuf
測試前端proto環境是否是安裝好了,若是有版本就是安裝好了。json
protoc --version
在進行先後端交互以前,前端須要進行編譯proto文件。
test.proto爲前端以及後端相同的proto文件。先編譯爲js文件再執行。首先進入node項目的proto的目錄下面,執行下面的命令以後會生成test_pb.js文件。最後js只須要解析這個文件便可。前端也須要執行這樣的操做,由於我這邊是先後端分離的。是兩個項目,因此兩個項目都須要編譯。axios
protoc --js_out=import_style=commonjs,binary:. test.proto
後端賦值proto文件的內容並傳給前端。
後端傳protobuf二進制給前端,要先轉化爲json才能夠給前端。否則的話前端會轉化成亂碼的。前端須要請求此路由。windows
app.get('/proto/get', function (req, res) { let protobuf = require('protocol-buffers') let messages=protobuf(fs.readFileSync('./proto/test.proto') let buf = messages.Test.encode({ num: 42, payload: 'hello world node js and javahhh呵呵呵', payloads: '' }) console.log(buf) // 打印出來的是二進制流 res.send(JSON.stringify(buf)); //須要進行json化而後給前端。否則的話瀏覽器會自動解析成文字的 })
前端須要進行接受二進制流
先引入proto.js文件以及protobufjs插件後端
import awesome from '../../proto/test_pb.js'
前端用axios請求/proto/get的路由,在回調函數裏的res.data爲後端的返回值。進行如下操做。打印出來的message3也是解析好的文件。瀏覽器
axios({ method:'get', url: '/proto/get', headers: { 'contentType':'application/x-protobuf'} }).then(res => { let message3 = awesome.Test.deserializeBinary(res.data.data) let nums = message3.getNum() console.log(nums) // nums=42。解析出來就是後端傳過來的42 let pm = awesome.Test.deserializeBinary(res.data.data) let protoBuf = pm.toObject() console.log('protoBuf: ', protoBuf) // 打印出來是一個對象 }).catch((error) => { console.log(error) })
前端須要進行proto文件的賦值以及轉換爲二進制給後端
引入須要依賴的文件。
import awesome from '../../proto/test_pb.js' import protobuf from 'protobufjs'
let message = new awesome.Test() // 調用Person對象 實例化 // 賦值 message.setNum(23) message.setPayload('asd') // 序列化 let bytes = message.serializeBinary() // 字節流 let blob = new Blob([bytes], {type: 'buffer'}); axios({ method:'post', url: '/proto/send', data: blob, headers: { 'Content-Type': 'application/octet-stream' // 這裏根據後臺要求進行設置的,若是沒有要求應該是 application/octet-stream (二進制流) } }).then(res => { console.log(res) }).catch((error) => { console.log(error) })
後端須要接受文件
引入文件
let BufferHelper = require('bufferhelper');
接收字節流的代碼
app.post('/proto/send', function (req, res) { let bufferHelper = new BufferHelper(); req.on("data", function (chunk) { bufferHelper.concat(chunk); }); req.on('end', function () { let protobuf = require('protocol-buffers') let buffer = bufferHelper.toBuffer(); console.log(buffer) // 這裏已經就是二進制文件了 let message3 = awesome.Test.deserializeBinary(buffer) console.log(message3.getNum()) // 打印的就是前端傳的23 let pm = awesome.Test.deserializeBinary(buffer) let protoBuf = pm.toObject() console.log(protoBuf) // 打印的是{ num: 23, payload: 'asd', payloads: 'asds' } console.log(protoBuf.num) // 打印23 }); })
以上就是關於protobuf的先後交互。若有錯誤,請指出。