Node.js从Google Bucket读二进制文件遇非法偏移,求最佳方案
Illegal offset: 0 <= 1 (+1) <= 1 问题背景
我手动将后缀为.tx的二进制文件上传至GCS的fabriccerts存储桶,需要在Cloud Function中读取该文件并使用fabric-client模块解析。本地Ubuntu环境读取文件后能正常解析,但在Cloud Function中执行时触发了偏移量错误。
现有代码
读取GCS文件的工具函数:
const {Storage} = require('@google-cloud/storage'); const storage = new Storage(); async function getFileContent(fileName, bucketName) { const myBucket = storage.bucket(bucketName); const file = myBucket.file(fileName); const content = await file.download(); return content; };
Cloud Function中调用解析的代码:
const Client = require('fabric-client'); let envelope_bytes = await storage_util.getFileContent("channel.tx", "fabriccerts"); console.log("file data" + envelope_bytes); let config_update = client.extractChannelConfig(envelope_bytes);
错误信息
执行时触发的错误日志:
Error: function terminated. Recommended action: inspect logs for termination reason. Details: Illegal offset: 0 <= 1 (+1) <= 1 RangeError: Illegal offset: 0 <= 1 (+1) <= 1 at ByteBuffer.module.exports.ByteBufferPrototype.readVarint32 (/srv/node_modules/bytebuffer/dist/bytebuffer-node.js:1540:23) at Message.ProtoBuf.Reflect.MessagePrototype.decode (/srv/node_modules/fabric-client/node_modules/protobufjs/dist/protobuf.js:3237:36) at Function.Message.decode (/srv/node_modules/fabric-client/node_modules/protobufjs/dist/protobuf.js:2952:37) at Client.extractChannelConfig (/srv/node_modules/fabric-client/lib/Client.js:660:42) at Object.exports.createChannel (/srv/chainmanagement/channel-management.js:36:30) at <anonymous> at process._tickDomainCallback (internal/process/next_tick.js:229:7)
本地与Cloud Function读取数据差异
- 本地Ubuntu读取后的文件数据:
� ����" mychannel� � mychannel;) Application Org1MSP Org2MSP Consortium�� Application� Org2MSP Org1MSP& Capabilities V1_4_2Admins"" WritersAdmins"" Admins AdminsAdmins"" ReadersAdmins*Admins" Consortium SampleConsortium
- Cloud Function读取后的文件数据:
� ����" mychannel� � mychannel;) Application Org1MSP� Org2MSP� Consortium��� Application� Org2MSP� Org1MSP�& Capabilities V1_4_2�Admins"" Writers WritersAdmins"" Admins AdminsAdmins"" Readers ReadersAdmins*Admins" Consortium SampleConsortium
疑问
- 读取此类二进制文件是否有特定方式?
- 下载后是否需要转换文件?
- 是否需要向Google提交bug?
解决方案与分析
这个问题的核心是你没有正确处理file.download()的返回值。
问题根源
@google-cloud/storage的file.download()方法默认返回的是一个包含Buffer的数组(格式为[Buffer]),而不是直接返回Buffer对象。你本地读取文件时应该是直接获取到了Buffer,所以解析正常;但在Cloud Function中,你把整个数组传给了extractChannelConfig,而fabric-client内部的ByteBuffer处理逻辑期望的是Buffer/Uint8Array类型,传入数组会导致偏移量计算错误,触发RangeError。
修复代码
修改你的getFileContent函数,通过解构获取数组中的第一个元素(也就是实际的二进制Buffer):
async function getFileContent(fileName, bucketName) { const myBucket = storage.bucket(bucketName); const file = myBucket.file(fileName); // 解构获取数组中的Buffer对象 const [content] = await file.download(); return content; };
验证说明
修改后,envelope_bytes会是标准的Buffer类型,和你本地读取的文件数据格式完全一致,extractChannelConfig就能正常解析了。
对你疑问的解答
- 读取二进制文件不需要特殊方式,只要确保拿到的是Buffer即可,不要指定
download()的encoding参数(保持默认的null,返回Buffer)。 - 不需要转换文件,只需要正确提取
download()返回的Buffer即可。 - 这不是Google的bug,是对GCS SDK返回值的理解偏差,不需要提交bug。
内容的提问来源于stack exchange,提问作者Jax

