Google Cloud Storage NodeJS流式读取首字符异常排查求助
问题成因与解决方法
成因
你看到的首个无效字符是UTF-8字节顺序标记(BOM),对应Unicode码点U+FEFF,字节层面为0xEF 0xBB 0xBF。这类标记是文件以「带BOM的UTF-8」格式保存时自动添加的。
file.download()方法在下载完整文件时,底层会自动处理并去除BOM;但createReadStream()是直接读取原始字节流,不会做额外处理,所以这个BOM会被保留在数据流开头。
另外注意:file.createReadStream()返回的是可读流对象,不是Promise,你代码里的await是多余的,直接调用即可。
解决方法
方法1:用第三方流处理包去除BOM
使用strip-bom-stream包自动过滤流中的BOM:
- 安装依赖:
npm install strip-bom-stream
- 修改代码:
const stripBomStream = require('strip-bom-stream'); async readFileStream(bucket, filename) { const myBucket = this.storage.bucket(bucket); const file = myBucket.file(filename); // 将原始流通过strip-bom-stream处理后返回 const stream = file.createReadStream().pipe(stripBomStream()); stream.on('data', (data) => { console.log(data.toString()); // 开头的BOM已被去除 }); return stream; }
方法2:手动处理流的首个Chunk
不想引入第三方包的话,可自行判断并截取首个Chunk中的BOM:
async readFileStream(bucket, filename) { const myBucket = this.storage.bucket(bucket); const file = myBucket.file(filename); const stream = file.createReadStream(); let isFirstChunk = true; stream.on('data', (data) => { if (isFirstChunk) { isFirstChunk = false; // 检查是否包含UTF-8 BOM的字节序列 if (data.length >= 3 && data[0] === 0xEF && data[1] === 0xBB && data[2] === 0xBF) { data = data.slice(3); } } console.log(data.toString()); }); return stream; }
方法3:从源头消除BOM
如果有权限修改GCS中的文件,将文件重新保存为「不带BOM的UTF-8」格式,后续无论用哪种方式读取都不会出现该问题。
内容的提问来源于stack exchange,提问作者Sean Clark
相关产品推荐
相关产品推荐

