写点什么

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

用户头像
CC同学
关注
发布于: 2021 年 07 月 12 日

背景需求:

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


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

方案 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();                        return pageHelper.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(); return pageHelper.showNoneToast('单张图片大小不能超过 ' + this.data.imgUploadSize + 'M', 3000); }
// 图片校验 if (this.data.isCheck) { let that = this; let callback = async function (path) { let check = await contentCheckHelper.imgCheckCloud(path); if (!check) { wx.hideLoading(); return false; //return pageHelper.showNoneToast('存在不合适的图片, 已屏蔽', 3000); } that.setData({ imgList: that.data.imgList.concat(path) }); that.triggerEvent('myImgUploadEvent', that.data.imgList); return true; }
// 图片大于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(); } }); },
复制代码


云端

async function 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)
throw new AppError('图片内容不合适,请修改');
} catch (err) { console.log('imgcheck ex', err);
if (err.errMsg && err.errMsg.includes('invalid media size')) throw new AppError('图片过大,请修改'); else if (err.errMsg && err.errMsg.includes('content size out of limit')) throw new AppError('图片尺寸过大,请修改'); else if (err.errMsg && err.errMsg.includes('604102')) throw new AppError('图片过大,请上传较小图片'); else throw new AppError('图片内容不合适,请修改');}
复制代码


}


测试情况:

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



发布于: 2021 年 07 月 12 日阅读数: 10
用户头像

CC同学

关注

CC同学的小程序开发笔记 2021.06.13 加入

大鹅厂的小小程序媛,vx: cclinux0730

评论

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