如何用fetch替代readFileSync生成与本地一致的证书Buffer?
解决fetch获取远程证书文件与本地readFileSync生成Buffer不一致的问题
想用fetch替代readFileSync从远程获取p12证书,生成和本地读取完全一致的Buffer,但两者结果不同。当前代码及输出如下:
const fs = require('fs'); const fsBuffer = fs.readFileSync('./FPTestcert4_20220818.p12'); const res = await fetch('https://www.bankid.com/assets/bankid/rp/FPTestcert4_20220818.p12'); const wBuffer = await res.arrayBuffer(); const wBuffer2 = Buffer.from(wBuffer, 'utf8'); console.log(fsBuffer); console.log(wBuffer2);
输出:
<Buffer 30 82 0b 09 02 01 03 30 82 0a cf 06 09 2a 86 48 86 f7 0d 01 07 01 a0 82 0a c0 04 82 0a bc 30 82 0a b8 30 82 05 6f 06 09 2a 86 48 86 f7 0d 01 07 06 a0 ... 2779 more bytes> <Buffer 3c 21 44 4f 43 54 59 50 45 20 68 74 6d 6c 3e 0a 3c 68 74 6d 6c 20 6c 61 6e 67 3d 22 65 6e 22 3e 0a 3c 68 65 61 64 3e 0a 20 20 20 20 3c 74 69 74 6c 65 ... 2840 more bytes>
问题分析
从输出能直接看出:
wBuffer2的Buffer开头是<DOCTYPE html>,说明你请求到的根本不是证书文件,而是HTML页面——大概率是请求被重定向、URL失效,或者服务器对请求做了拦截返回网页。- 代码里把
arrayBuffer转Buffer时指定了'utf8'编码,p12是二进制文件,这种转换会直接破坏原始二进制数据,哪怕请求到正确文件也会生成错误的Buffer。
解决步骤
1. 修正Buffer转换逻辑
二进制数据直接转Buffer即可,不需要指定编码:
const fetchBuffer = Buffer.from(arrayBuffer); // 去掉'utf8'参数
2. 确保请求拿到正确的二进制文件
添加请求校验,确认响应的有效性:
const fs = require('fs'); const fsBuffer = fs.readFileSync('./FPTestcert4_20220818.p12'); const res = await fetch('https://www.bankid.com/assets/bankid/rp/FPTestcert4_20220818.p12'); // 校验请求是否成功 if (!res.ok) { throw new Error(`请求失败,状态码:${res.status}`); } // 确认响应的文件类型 const contentType = res.headers.get('Content-Type'); console.log('响应类型:', contentType); // 正常应该返回application/x-pkcs12或application/octet-stream const arrayBuffer = await res.arrayBuffer(); const fetchBuffer = Buffer.from(arrayBuffer); // 验证两个Buffer是否完全一致 console.log('Buffer是否相等:', Buffer.compare(fsBuffer, fetchBuffer) === 0);
3. 用axios实现的替代方案
如果fetch还是有问题,可以用axios,直接指定响应类型为二进制:
const fs = require('fs'); const axios = require('axios'); const fsBuffer = fs.readFileSync('./FPTestcert4_20220818.p12'); const response = await axios.get('https://www.bankid.com/assets/bankid/rp/FPTestcert4_20220818.p12', { responseType: 'arraybuffer' // 关键:指定接收二进制数据 }); const axiosBuffer = Buffer.from(response.data); console.log('Buffer是否相等:', Buffer.compare(fsBuffer, axiosBuffer) === 0);
额外排查点
如果还是返回HTML页面,需要:
- 检查URL是否拼写正确;
- 尝试添加请求头(比如
User-Agent模拟浏览器请求),部分服务器会拦截非浏览器请求; - 确认目标文件是否公开可访问,是否需要权限验证。
内容的提问来源于stack exchange,提问作者j.d.o.
相关产品推荐
相关产品推荐

