微信小程序从云函数获取到的二维码d Buffer, 生成图片从而生成海报。
- 坑1:小程序对base64图片支持不友好,模拟器上图片可以显示,真机无法显示
- 坑2:小程序canvas绘图必须使用网络图片或者本地图片,但是如果直接在wx.drawImage传入图片链接,真机上面会显示失败
解决思路:服务器生成二维码图片,微信小程序下载服务器图片。
微信小程序 cloud.openapi.wxacode.getUnlimited 返回给前端的 Buffer 类型是 ArrayBuffer, 转 Int8Array 类型传给后台, 后台 使用 fs.writeFileSync 生成图片
微信小程序代码
const bufferToImageURL = (buffer, fileName) => {
return new Promise((resolve, reject) => {
let arr = new Int8Array(buffer)
let parameters = {
arr: arr,
fileName: fileName,
byteLength: buffer.byteLength
};
wx.request({
url: 'url', // 服务器生成图片的接口
data: parameters,
method: "POST",
success(result) {
if (result.statusCode === 200) {
wx.downloadFile({
url: 'url', // 服务器返回图片的地址
success (res) {
if (res.statusCode === 200) {
resolve(res.tempFilePath)
} else {
reject(new Error("请求生成二维码成功, 下载二维码失败"));
}
}
})
} else {
reject(new Error("请求生成二维码失败"));
}
},
fail(err) {
reject(new Error("请求生成二维码失败" + JSON.stringify(err)));
}
});
})
}
服务器代码,使用 nodejs
// router
router.post('/qrCode/bufferToImage.fp', bufferToImage)
router.get('/download/wxImage/:fileName', downloadwxImage)
// controller
exports.downloadwxImage = async function (ctx, next) {
try {
var fileName = ctx.params.fileName;
ctx.type = 'image/jpeg'; // 设置请求头类型
let data = fs.readFileSync('public/tmp/' + fileName);
ctx.body = data;
fs.unlink('public/tmp/' + fileName); // 删除图片
} catch (e) {
ctx.body = false;
}
}
exports.bufferToImage = async function (ctx, next) {
try {
var inputParams = ctx.request.body;
let byteLength = inputParams.byteLength
let data = [];
for (let i = 0; i < byteLength; i++) {
data.push(inputParams.arr[i]); // new Int8Array() 返回的是一个对象, 从中取出值
}
// 转 Buffer
var buffer = Buffer.from(data);
var fileName = inputParams.fileName;
// 保存为图片格式
fs.writeFileSync('public/tmp/' + fileName, buffer, 'binary')
ctx.body = {
fileName
};
} catch (e) {
ctx.body = {
success: false,
message: e.message
}
}
};