Node.js中base64转Buffer与fs.readFile结果不一致致上传文件损坏
问题根因
核心错误是Base64字符串转Buffer时未指定解码编码,导致生成的Buffer内容不是原始文件字节:
- 当你调用
Buffer.from(base64Str)且不传入第二个编码参数时,Node.js默认会按UTF-8编码,把Base64字符串本身的文本内容转成字节存储,得到的是Base64文本的字节,而非Base64解码后的原始文件二进制内容。 - 这也直接对应你观察到的长度差异:Base64编码本身会让原始二进制内容膨胀约33%,因此错误生成的Buffer长度会比
fs.readFileSync读取到的原始文件Buffer更长,把这个内容当文件上传,本质是上传了一段Base64文本,自然会出现文件损坏的问题。
你测试代码里的转换逻辑问题可以直接通过长度验证:
const localFile = fs.readFileSync('/iconQA.png'); const base64FromTestFile = localFile.toString('base64'); // 错误写法:得到的是base64文本的字节,长度更长 const wrongBuffer = Buffer.from(base64FromTestFile); console.log(wrongBuffer.length === Math.ceil(localFile.length * 4 / 3)); // 输出true // 正确写法:指定base64编码解码,得到原始文件字节 const correctBuffer = Buffer.from(base64FromTestFile, 'base64'); console.log(correctBuffer.length === localFile.length); // 输出true
修复方案
- 所有从Base64字符串还原文件Buffer的场景,必须在
Buffer.from的第二个参数明确传入'base64',告诉Node.js将输入字符串按Base64规则解码为原始二进制内容。 - 修正后对应业务代码的转换逻辑为:
// 替换原来错误的Buffer生成逻辑 const bufferFromFile = Buffer.from(base64FromTestFile, 'base64'); const bufferRequest = Buffer.from(base64FromRequest, 'base64'); // 此时将Buffer传入form-data的append方法,效果和直接读取本地文件上传完全一致 const params = new FormData(); params.append('f', 'json'); params.append('token', token); params.append('attachment', bufferRequest, 'upload.png');
- 额外校验点:如果请求传入的Base64字符串带Data URL前缀(格式类似
data:image/png;base64,开头),需要先把前缀部分截取移除,再传入做Base64解码,否则前缀文本会被混入二进制内容,同样会导致文件损坏。
内容的提问来源于stack exchange,提问作者Porco
相关产品推荐
相关产品推荐

