如何在JS中反序列化Python后端发送的Protobuf字符串?
问题修复:Flask Protobuf 后端与 protobuf.js 前端兼容问题
核心问题根源
- 后端响应头缺失:Flask 返回二进制 Protobuf 数据时,未设置正确的
Content-Type,导致 jQuery 默认将响应解析为 UTF-8 文本,二进制数据被错误转换(非UTF-8字符被替换为无效占位符)。 - 前端处理错误:用
TextEncoder对已损坏的文本进行编码,完全偏离了 Protobuf 二进制数据的处理逻辑,自然无法完成解码。
修复步骤
1. 修正 Flask 后端代码
给返回的二进制数据添加正确的响应头,确保浏览器识别为二进制流:
from flask import Flask, make_response from flask import render_template, request import vtkMessage_pb2 app = Flask(__name__, static_folder='') @app.route('/test',methods = ['POST']) def test(): data = request.get_json() ret = vtkMessage_pb2.vtkMsg() ret.tris.extend([1,2,3]) ret.verts.extend([0.45,0.35,0.11, 0.66,0.78,0.23, 0.11,0.01,0.14]) a = ret.vals.elem.add() a.name = 'test1' a.v.extend([0.1, 0.2]) a = ret.vals.elem.add() a.name = 'test2' a.v.extend([0.3, 0.5]) print(ret) # 关键修复:构造二进制响应并设置正确的MIME类型 proto_data = ret.SerializeToString() response = make_response(proto_data) response.headers['Content-Type'] = 'application/octet-stream' return response @app.route('/protoTest') def protoTest(): return render_template('protoTest.html')
2. 修正前端 JavaScript 代码
告诉 jQuery 直接接收二进制 ArrayBuffer,而非自动解析为文本:
<html> <meta charset="UTF-8"> <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script> <script src="//cdn.jsdelivr.net/npm/protobufjs@7.2.5/dist/protobuf.js"></script> <script type="text/javascript"> window.onload = main; function main() { var dat = JSON.stringify({ step: 0, frames: 1, fname: "openfoam.vtk" }); protobuf.load('vtkMessage.proto', function(err,root) { window.vtkMsg = root.lookupType("vtkMessage.vtkMsg"); var proto_obj = {}; $.ajax({ url:'/test', data: dat, type: "POST", contentType: "application/json;charset=utf-8", async: false, // 关键设置:要求返回ArrayBuffer类型的二进制数据 xhrFields: { responseType: 'arraybuffer' }, success: function(res) { console.log(res); // 此时res为ArrayBuffer // 用Uint8Array包装后直接解码 proto_obj = vtkMsg.decode(new Uint8Array(res)); console.log(proto_obj); }, error: function(res) { console.error(res); } }); console.log(proto_obj); }); } </script> <body> <h1>Protobuf test, view in console</h1> </body> </html>
额外说明
- 生成 Python Protobuf 代码的命令
protoc -I=. --python_out=. vtkMessage.proto是正确的,无需修改。 - 修复后,前端接收到的是原始的 Protobuf 二进制数据,直接用
Uint8Array包装后即可被 protobuf.js 正确解码。
内容的提问来源于stack exchange,提问作者lee
相关产品推荐
相关产品推荐

