前後端交互protobuf介紹

protobuf介紹

由於網上關於protobuf的交互的資料比較零散,所以自己整理了一下關於protobuf前後端交互的資料,以作參考。

Google Protocol Buffers 簡稱 Protobuf,它提供了一種靈活、高效、自動序列化結構數據的機制,可以聯想 XML,但是比 XML 更小、更快、更簡單。僅需要自定義一次你所需的數據格式,然後用戶就可以使用 Protobuf 編譯器自動生成各種語言的源碼,方便的讀寫用戶自定義的格式化的數據。與語言無關,與平臺無關,還可以在不破壞原數據格式的基礎上,依據老的數據格式,更新現有的數據格式。

前後端交互方式

前後端都是以二進制形式進行交互信息。前後端定義proto後綴的文件,以此文件來當文檔來進行溝通。

protobuf文件形式

以下爲protobuf文件的demo,test.proto,文件的結構確實簡單明瞭。

enum FOO {
  BAR = 1;
}

message Test {
  required float num  = 1;
  required string payload = 2;
  optional string payloads = 3;
}

message AnotherOne {
  repeated FOO list = 1;
}

前後端進行protobuf的環境安裝

後端以node爲例子:
安裝bufferhelper以及protocol-buffers進行解析protobuf文件

npm install bufferhelper
npm install protocol-buffers

前端需要安裝解析protobuf的環境。
mac使用brew安裝protobuf環境。此操作需要先安裝Homebrew環境。具體的Homebrew的安裝自行搜索。
windows的前端環境安裝有點不一樣,自行搜索。

brew install protobuf

測試前端proto環境是不是安裝好了,如果有版本就是安裝好了。

protoc --version

在進行前後端交互之前,前端需要進行編譯proto文件。
test.proto爲前端以及後端相同的proto文件。先編譯爲js文件再執行。首先進入node項目的proto的目錄下面,執行下面的命令之後會生成test_pb.js文件。最後js只需要解析這個文件即可。前端也需要執行這樣的操作,因爲我這邊是前後端分離的。是兩個項目,所以兩個項目都需要編譯。

protoc --js_out=import_style=commonjs,binary:. test.proto

後端給前端傳數據

後端賦值proto文件的內容並傳給前端。
後端傳protobuf二進制給前端,要先轉化爲json纔可以給前端。不然的話前端會轉化成亂碼的。前端需要請求此路由。

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的前後交互。如有錯誤,請指出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章