You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JS中反序列化Python后端发送的Protobuf字符串?

问题修复:Flask Protobuf 后端与 protobuf.js 前端兼容问题

核心问题根源

  1. 后端响应头缺失:Flask 返回二进制 Protobuf 数据时,未设置正确的 Content-Type,导致 jQuery 默认将响应解析为 UTF-8 文本,二进制数据被错误转换(非UTF-8字符被替换为无效占位符)。
  2. 前端处理错误:用 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 07:16:03