共计 3667 个字符,预计需要花费 10 分钟才能阅读完成。
背景需要:
我集体做了一款校友交换的小程序。外面有校友相册,校友团聚,校友资讯,校友互助等性能,校友从本地相册选一张或者多张图片后,连同文章内容保留到服务器。这里就波及到内容平安了,提交审核没有通过也是因为这个没有做内容平安。避免一些色情低俗的事件产生。
以后可用的图片审核计划的优缺点:
计划 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 亟待解决的问题:
- 图片大小限度 1M
- 图片尺寸限度的问题(官网表述 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, // 默认 9 | |
sizeType: ['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 次,全副通过。校友会小程序上线后暂无发现检测失败状况。