小程序圖片安全檢查

藉助臨時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 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章