小程序图片安全检查

借助临时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 }
posted @ 2022-10-27 09:45  wx_xfy6369  阅读(180)  评论(0编辑  收藏  举报