小程序图片安全检查
借助临时CDN传递大数据到云函数实现图片安全检测
最近在重构小程序恋爱小清单,在用云函数做图片的安全检测时报了一个错:cloud.callFunction:fail Error: data exceed max size
也就是图片超过了大小限制。
早期的版本是通过画布将图片缩小(wx.canvasToTempFilePath),接着读取文件流(wx.getFileSystemManager().readFile),然后再提交云函数检测,过程感觉有些繁琐复杂
最近发现其实有更简单的方法,可以借助临时的CDN,传递大数据,最终在云函数端会收到一个CDN地址,接着通过request-promise读取文件流,然后再做安全检测,相比旧版的方法个人感觉简单清爽不少。
参考官方文档:
https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/utils/Cloud.CDN.html
代码如下:
小程序端:
const api = require("api.js");
/**
* 图片安全检测
* 借助临时CDN传递大数据
* @param filePath 图片的临时文件路径 (本地路径)
* @returns {Promise<unknown>}
*/
const imgSecCheckViaCDN = (filePath) => {
return new Promise(function (resolve, reject) {
api.callCloudFunction("securityCheck", {
type: "imgSecCheckViaCDN",
imgData: wx.cloud.CDN({
type: "filePath",
filePath,
})
}, res => {
console.log("图片安全检测结果:", JSON.stringify(res));
const result = res.result;
if (result.success) {
resolve(result);
} else {
reject(result);
}
}, reject);
});
}
api.js
/**
* 云函数调用
* @param name
* @param data
* @param success
* @param fail
* @param complete
*/
const callCloudFunction = function (name, data, success, fail, complete) {
//执行云函数
wx.cloud.callFunction({
// 云函数名称
name: name,
// 传给云函数的参数
data: Object.assign({}, data, {env: env.activeEnv})
}).then(res => {
typeof success == 'function' && success(res);
}).catch(res => {
typeof fail == 'function' && fail(res);
}).then(res => {
typeof complete == 'function' && complete(res);
});
};
module.exports = {callCloudFunction}
云函数端:
// 云函数入口文件
const cloud = require('wx-server-sdk');
const responce = require('easy-responce');
const requestHelper = require('./utils/requestHelper');
const headers = {
encoding: null,
headers: {
"content-type": "application/octet-stream",
// "content-type": "video/mpeg4",
},
};
// 云函数入口函数
exports.main = async (event, context) => {
cloud.init({
env: event.env
});
let result = {};
try {
const {type, content, imgData} = event;
let {buffer} = event;
console.log("检测类型:", type, "文本内容:", content, "图片内容:", imgData);
switch (type) {
case "imgSecCheckViaCDN":
const imageResponse = await requestHelper.request(imgData, headers, {});
buffer = imageResponse.body;
case "imgSecCheck":
result = await cloud.openapi.security.imgSecCheck({
media: {
contentType: 'image/png',
// value: Buffer.from(imgBase64, "base64")
value: Buffer.from(buffer)
}
});
break;
case "msgSecCheck":
result = await cloud.openapi.security.msgSecCheck({content});
break;
default:
console.log("不支持的检测类型:", type);
break;
}
} catch (e) {
console.error(e);
result = e;
}
console.log("检测结果:", result);
const {errCode, errMsg} = result;
return errCode !== 87014 ? responce.success({errCode}) : responce.fail(errMsg);
};
requestHelper.js
const rp = require('request-promise');
/**
* http请求
* @param url
* @param options
* @param data
* @param autoFollowRedirect
* @returns {Promise<unknown>}
*/
const request = function (url, options, data, autoFollowRedirect = true) {
return new Promise(function (resolve, reject) {
const p = Object.assign({
json: true,
resolveWithFullResponse: true,
followRedirect: autoFollowRedirect
}, options, data, {url});
console.log("请求参数:", JSON.stringify(p));
return rp(p)
.then(async function (repos) {
//console.log("获取到最终内容,执行回调函数:", repos);
return resolve(repos);
})
.catch(async function (err) {
if (err && (err.statusCode === 301 || err.statusCode === 302)) {
// console.log("停止重定向,重定向信息:", err);
console.log("停止重定向");
return resolve(err);
}
console.error("重定向失败:", err);
return reject(err);
});
});
}
module.exports = {request }