小程序图片安全审核方案与security.imgSecCheck不能校验超过1M图片的解决思路

背景需求:

我个人做了一款校友交流的小程序。里面有校友相册,校友聚会,校友资讯,校友互助等功能,校友从本地相册选一张或者多张图片后,连同文章内容保存到服务器。这里就涉及到内容安全了,提交审核没有通过也是因为这个没有做内容安全。防止一些色情低俗的事情发生。




当前可用的图片审核方案的优缺点:

方案1 :小程序自带的同步同步API:security.imgSecCheck

优点:小程序自带,无须额外申请,格式支持PNG、JPEG、JPG、GIF,单个 appId 调用上限为 2000 次/分钟,200,000 次/天,基本满足需要

缺点:图片大小限制1M ,图片尺寸不超过 750px x 1334px

虽然有图片尺寸限制,但是在实际应用中发现,尺寸到4000 x 4000都可以,但是4000以上会出现问题


方案2 :小程序自带的异步API: security.mediaCheckAsync

优点:单个文件大小不超过10M,解决手机拍照或者相册里的大图片限制

缺点:属于异步调用,必须先上传图片,处理不及时,最多可能30分钟才返回结果,需要提供回调URL来接受处理结果,不健康的图片无法实时处理,容易造成风险


方案3: 小程序服务市场的珊瑚图片安全

优点:非常好用,但是已经下架(2021年4月9日),无比郁闷




方案4: 小程序服务市场的天御

才上线没多久,按官方给出的文档无法正常调用成功,而且只有30天的免费使用时长




方案5 :腾讯云:T-Sec 天御 图片内容安全

优点:能精准识别图片中出现可能令人反感、不安全或不适宜内容,支持配置图片黑名单,识别自定义的图片类型。

缺点:文档调用复杂,价格高昂




方案6 :百度云:内容审核平台

 优点:基于深度学习的智能内容审核方案,准确过滤图像和视频中的色情、暴恐、政治敏感、广告、恶心、不良场景等违规内容,也能从美观、

清晰等维度对图像进行筛选,紧贴业务需求,释放审核人力

缺点:1)还是价格!!!2)接入成本

我的解决思路

综合上述方案优缺点,我还是选择方案1(security.imgSecCheck),原因如下

1 小程序自带的API,调用方便,尤其是云函数调用方便

2 没有额外的申请流程

3 没有费用开销

4 量度次数上限基本满足我的校友录小程序需求


security.imgSecCheck 亟待解决的问题:

1. 图片大小限制1M

2.  图片尺寸限制的问题(官方表述750px x 1334px)



 我的解决方案

虽然官方文档有些图片尺寸的上限,这也是当时我犹豫不决的原因,

但是在实际应用中发现,尺寸到4000 x 4000都可以实现检测,但是4000px以上会出现问题,

实际图片中出现上述大尺寸的少,所以可以暂且忽略,

只需要针对图片大于1M的进行压缩处理


大于1M的图片 思路:校友会小程序相册选图片 --> 判断图片是否大于1M --> 压缩图片 --> 上传图片流给security.imgSecCheck检测-->通过-->保存

小于1M的图片 思路:校友会小程序相册选图片 --> 判断图片是否大于1M --> 不压缩图片 --> 上传图片流给security.imgSecCheck检测-->通过-->保存


代码实现:

小程序端

/**

        * 选择上传图片

        */        bindChooseImgTap: function (e) {

            wx.chooseImage({

                count: this.data.imgMax -this.data.imgList.length,//默认9sizeType: ['compressed'],//可以指定是原图还是压缩图,默认二者都有sourceType: ['album', 'camera'],//从相册选择success: async (res) => {

                    wx.showLoading({

                        title: '图片校验中',

                        mask: true                    });

                    for(let k = 0; k < res.tempFiles.length; k++) {

                        let size = res.tempFiles[k].size;

                        let path = res.tempFiles[k].path;

                        if(!contentCheckHelper.imgTypeCheck(path)) {

                            wx.hideLoading();

                            returnpageHelper.showNoneToast('只能上传png、jpg、jpeg格式', 3000);

                        }

                        let imageMaxSize = 1024 * 1000 *this.data.imgUploadSize;

                        console.log('IMG SIZE=' + size + ',' + size / 1024 + 'K');

                        if(!contentCheckHelper.imgSizeCheck(size, imageMaxSize)) {

                            wx.hideLoading();

                            returnpageHelper.showNoneToast('单张图片大小不能超过 ' +this.data.imgUploadSize + 'M', 3000);

                        }

                        // 图片校验if(this.data.isCheck) {

                            let that =this;

                            let callback = asyncfunction (path) {

                                let check = await contentCheckHelper.imgCheckCloud(path);

                                if(!check) {

                                    wx.hideLoading();

                                    returnfalse;

                                    //return pageHelper.showNoneToast('存在不合适的图片, 已屏蔽', 3000);                                }

                                that.setData({

                                    imgList: that.data.imgList.concat(path)

                                });

                                that.triggerEvent('myImgUploadEvent', that.data.imgList);

                                returntrue;

                            }

                            // 图片大于1M,压缩if(size > 1000 * 1000) {

                                wx.compressImage({

                                    src: path, // 图片路径quality: 50,// 压缩质量fail:function () {

                                        pageHelper.showModal('上传失败,请重新上传');

                                    },

                                    success: async function (res) {

                                        await callback(res.tempFilePath);

                                    }

                                });

                            } else {

                                // 小于1M,不压缩if(!await callback(path))return;

                            }

                        }

                        else {

                            //图片无须审核this.setData({

                                imgList: this.data.imgList.concat(path)

                            });

                            this.triggerEvent('myImgUploadEvent',this.data.imgList);

                        }

                    }

                    wx.hideLoading();

                }

            });

        },


云端

asyncfunction checkImg(imgData, mine) {

    // 下载CDN图片进行检查const axios = require('axios');

    let buffer =null;

    await axios({

        method: 'get',

        url: imgData,

        responseType: 'arraybuffer'    }).then(res => {

        buffer = res.data;

    });

    console.log('buffer SIZE=' + buffer.length / 1024 + 'K');

    let cloud = cloudBase.getCloud();

    try {

        const result = await cloud.openapi.security.imgSecCheck({

            media: {

                contentType: 'image/png',

                value: buffer

                //value: Buffer.from(imgData, 'base64') // 这里必须要将小程序端传过来的进行Buffer转化,否则就会报错,接口异常            }

        });

        console.log('imgcheck', result);

        if(!result || result.errCode !== 0)

            thrownewAppError('图片内容不合适,请修改');

    } catch (err) {

        console.log('imgcheck ex', err);

        if(err.errMsg && err.errMsg.includes('invalid media size'))

            thrownewAppError('图片过大,请修改');

        elseif(err.errMsg && err.errMsg.includes('content size out of limit'))

            thrownewAppError('图片尺寸过大,请修改');

        elseif(err.errMsg && err.errMsg.includes('604102'))

            thrownewAppError('图片过大,请上传较小图片');

        elsethrownewAppError('图片内容不合适,请修改');

    }

}


测试情况:

校友会小程序中上传正常图片不含违法违规,测试50次,全部通过。校友会小程序上线后暂无发现检测失败情况。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351

推荐阅读更多精彩内容