vue2、vue3中使用pb(Base64编码)

/proto/chat.proto 文件

ini 复制代码
syntax = "proto3";

// 定义Protobuf的包名称空间,通过指定包名来避免message名字冲突
package com.xxx.protobuf.model;

// 指定生成的Java类的包名。若不指定该选项,则会以头部声明中的package作为Java类的包名。
option java_package = "com.xxx.protobuf.model";
// 指定生成Java类的打包方式。不指定则默认false,表示所有的消息都作为内部类,打包到一个外部类中。true表示一个消息对应一个Java的POJO类
option java_multiple_files = false;
// 指定生成的外部类名
option java_outer_classname = "ChatProtos";

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
}

message User {
  string name = 1;
  int32 id = 2;
  string email = 3;
}

/utils/protoParser.js 文件

typescript 复制代码
// src/utils/protoParser.js
import protobuf from 'protobufjs';

// vue2 import ChatProto from '@/proto/chat.proto';
// vue3 import ChatProto from '../proto/chat.proto?raw';

class ProtoParser {
  constructor() {
    this.root = null;
    this.loaded = false;
  }

  async init() {
    if (this.loaded) return;
    
    try {
      this.root = protobuf.parse(ChatProto, { keepCase: true }).root;
      this.loaded = true;
      console.log('Proto 文件加载成功');
    } catch (error) {
      console.error('Proto 文件解析失败:', error);
      throw error;
    }
  }

  async ensureInitialized() {
    if (!this.loaded) {
      await this.init();
    }
  }

  decodeMessage(type, msg) {
    try {
      let buffer;
      const binaryString = atob(msg);
      buffer = new Uint8Array(binaryString.length);
      for (let i = 0; i < binaryString.length; i++) {
          buffer[i] = binaryString.charCodeAt(i);
      }
      const MessageType = this.root.lookupType(`com.xxx.protobuf.model.${type}`);
      const message = MessageType.decode(buffer);
      const object = MessageType.toObject(message, {
        longs: String,
        enums: String,
        bytes: String,
        defaults: true,
        arrays: true,
        objects: true,
        oneofs: true
      });
      return object;
    } catch (error) {
      console.error(`解析消息类型 ${type} 失败:`, error,':msg:',msg);
      throw error;
    }
  }

  // 编码消息并返回字节数组
  async encodeMessage(type, object) {
    await this.ensureInitialized();
    
    try {
      const MessageType = this.root.lookupType(`com.xxx.protobuf.model.${type}`);
      
      // 验证对象
      const errMsg = MessageType.verify(object);
      if (errMsg) {
        console.warn(`验证消息 ${type} 失败:`, errMsg);
      }

      // 创建消息并编码
      const message = MessageType.create(object);
      const buffer = MessageType.encode(message).finish();
      return buffer;
    } catch (error) {
      console.error(`编码消息类型 ${type} 失败:`, error);
      throw error;
    }
  }

  // 编码消息并返回 base64 字符串(与安卓端格式一致)
  async encodeMessageToBase64(type, object) {
    await this.ensureInitialized();
    
    try {
      const buffer = await this.encodeMessage(type, object);
      return this.arrayBufferToBase64(buffer);
    } catch (error) {
      console.error(`编码消息为 Base64 失败:`, error);
      throw error;
    }
  }
  
  // ArrayBuffer 转 Base64
  arrayBufferToBase64(buffer) {
    let binary = '';
    const bytes = new Uint8Array(buffer);
    for (let i = 0; i < bytes.byteLength; i++) {
      binary += String.fromCharCode(bytes[i]);
    }
    return btoa(binary);
  }
  
  // Base64 转 ArrayBuffer
  base64ToArrayBuffer(base64) {
    const binaryString = atob(base64);
    const bytes = new Uint8Array(binaryString.length);
    for (let i = 0; i < binaryString.length; i++) {
      bytes[i] = binaryString.charCodeAt(i);
    }
    return bytes;
  }
}

export default new ProtoParser();

安装protobufjs

css 复制代码
npm i protobufjs -D

配置

  1. vue.config.js
arduino 复制代码
chainWebpack: config => {
    ......
    // 添加对 .proto 文件的支持
    config.module
        .rule('proto')
        .test(/\.proto$/)
        .use('raw-loader')
        .loader('raw-loader')
        .end();
},
  1. vite.config.js
vbnet 复制代码
assetsInclude: ['**/*.proto'],

使用

csharp 复制代码
await protoParser.init(); //页面初始化时执行
// 确保 protoParser 已初始化
protoParser.ensureInitialized();
// 解析数据
const SpeakMsgRes = protoParser.decodeMessage('Person', res.data);
console.log('聊天消息:', SpeakMsgRes);
相关推荐
xw533 分钟前
npm几个实用命令
前端·npm
!win !38 分钟前
npm几个实用命令
前端·npm
代码狂想家42 分钟前
使用openEuler从零构建用户管理系统Web应用平台
前端
dorisrv2 小时前
优雅的React表单状态管理
前端
蓝瑟2 小时前
告别重复造轮子!业务组件多场景复用实战指南
前端·javascript·设计模式
dorisrv3 小时前
高性能的懒加载与无限滚动实现
前端
韭菜炒大葱3 小时前
别等了!用 Vue 3 让 AI 边想边说,字字蹦到你脸上
前端·vue.js·aigc
StarkCoder3 小时前
求求你,别在 Swift 协程开头写 guard let self = self 了!
前端
清妍_3 小时前
一文详解 Taro / 小程序 IntersectionObserver 参数
前端
电商API大数据接口开发Cris3 小时前
构建异步任务队列:高效批量化获取淘宝关键词搜索结果的实践
前端·数据挖掘·api