前言
相比于文本的安全检测,图片的安全检测要稍微略复杂一些,当您读完本篇,将get到
- 图片安全检测的应用场景
- 解决图片的安全校验的方式
- 使用云调用方式对图片进行检测
- 如何对上传图片大小进行限制
- 如何解决多图上传覆盖问题
示例效果
当用户上传敏感违规图片时,禁止用户上传发布,并且做出相对应的用户友好提示
应用场景
通常,在校验一张图片是否含有违法违规内容相比于文本安全的校验,同样重要,有如下应用
图片智能鉴黄:涉及拍照的工具类应用(如美拍,识图类应用)用户拍照上传检测;电商类商品上架图片检测;媒体类用户文章里的图片检测等敏感人脸识别:用户头像;媒体类用户文章里的图片检测;社交类用户上传的图片检测等,凡是有用户自发生产内容的都应当提前做检测
解决图片的安全手段
在小程序开发中,提供了两种方式
- HTTPS调用
- 云调用
HTTPS 调用的请求接口地止
https://api.weixin.qq.com/wxa/img_sec_check"color: #ff0000">功能实现:小程序端逻辑
对于wxml与wxss,大家可以自行任意修改,本文重点在于图片安全的校验
<view class="image-list"> <!-- 显示图片 --> <block wx:for="{{images}}" wx:key="*this"><view class="image-wrap"> <image class="image" src="/UploadFiles/2021-04-02/{{item}}">对应的wxss代码
.footer { display: flex; align-items: center; width: 100%; box-sizing: border-box; background: #34bfa3; } .send-btn { width: 100%; color: #fff; font-size: 32rpx; background: #34bfa3; } button { border-radius: 0rpx; } button::after { border-radius: 0rpx !important; } /* 图片样式 */ .image-list { display: flex; flex-wrap: wrap; margin-top: 20rpx; } .image-wrap { width: 220rpx; height: 220rpx; margin-right: 10rpx; margin-bottom: 10rpx; position: relative; overflow: hidden; text-align: center; } .image { width: 100%; height: 100%; } .icon-shanchu { position: absolute; top: 0; right: 0; width: 40rpx; height: 40rpx; background-color: #000; opacity: 0.4; color: #fff; text-align: center; line-height: 40rpx; font-size: 38rpx; font-weight: bolder; } .selectphoto { border: 2rpx dashed #cbd1d7; position: relative; } .icon-add { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #cbd1d7; font-size: 60rpx; }最终呈现的UI,由于只是用于图片检测演示,UI方面可忽略,如下所示
对应的JS代码
/* * 涉及到的API:wx.chooseImage 从本地相册选择图片或使用相机拍照 *(https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseImage.html) * * */// 最大上传图片数量 const MAX_IMG_NUM = 9; const db = wx.cloud.database(); // 初始化云数据库 Page({ /** * 页面的初始数据 */ data: { images: [], // 把上传的图片存放在一个数组对象里面 selectPhoto: true, // 添加+icon元素是否显示 }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { }, // 选择图片 onChooseImage() { // 还能再选几张图片,初始值设置最大的数量-当前的图片的长度 let max = MAX_IMG_NUM - this.data.images.length; wx.chooseImage({ count: max, // count表示最多可以选择的图片张数 sizeType: ['original', 'compressed'], // 所选的图片的尺寸 sourceType: ['album', 'camera'], // 选择图片的来源 success: (res) => { // 接口调用成功的回调函数console.log(res) this.setData({ // tempFilePath可以作为img标签的src属性显示图片,下面是将后添加的图片与之前的图片给追加起来 images: this.data.images.concat(res.tempFilePaths) }) // 还能再选几张图片 max = MAX_IMG_NUM - this.data.images.length this.setData({ selectPhoto: max <= 0 "text-align: center">您现在看到的效果,没有任何云函数代码,只是前端的纯静态展示,对于一些涉嫌敏感图片,是有必要进行做过滤处理的
功能实现:云函数侧逻辑
在cloudfunctions目录文件夹下创建云函数imgSecCheck
并在该目录下创建config.json,配置参数如下所示
{ "permissions": { "openapi": [ "security.imgSecCheck" ] } }配置完后,在主入口index.js中,如下所示,通过security.imgSecCheck接口,并传入media对象
// 云函数入口文件 const cloud = require('wx-server-sdk'); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext() try { const result = await cloud.openapi.security.imgSecCheck({ media: { contentType: 'image/png', value: Buffer.from(event.img) // 这里必须要将小程序端传过来的进行Buffer转化,否则就会报错,接口异常 } }) if (result && result.errCode.toString() === '87014') { return { code: 500, msg: '内容含有违法违规内容', data: result } } else { return { code: 200, msg: '内容ok', data: result } } } catch (err) { // 错误处理 if (err.errCode.toString() === '87014') { return { code: 500, msg: '内容含有违法违规内容', data: err } } return { code: 502, msg: '调用imgSecCheck接口异常', data: err } } }您会发现在云函数端,就这么几行代码,就完成了图片安全校验
而在小程序端,代码如下所示
// miniprogram/pages/imgSecCheck/imgSecCheck.js // 最大上传图片数量 const MAX_IMG_NUM = 9; const db = wx.cloud.database() Page({ /** * 页面的初始数据 */ data: { images: [], selectPhoto: true, // 添加图片元素是否显示 }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { }, // 选择图片 onChooseImage() { // const that = this; // 如果下面用了箭头函数,那么这行代码是不需要的,直接用this就可以了的// 还能再选几张图片,初始值设置最大的数量-当前的图片的长度 let max = MAX_IMG_NUM - this.data.images.length; wx.chooseImage({ count: max, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { // 这里若不是箭头函数,那么下面的this.setData的this要换成that上面的临时变量,作用域的问题,不清楚的,可以看下this指向相关的知识 console.log(res) // tempFilePath可以作为img标签的src属性显示图片 const tempFiles = res.tempFiles; this.setData({ images: this.data.images.concat(res.tempFilePaths) }) // 在选择图片时,对本地临时存储的图片,这个时候,进行图片的校验,当然你放在最后点击发布时,进行校验也是可以的,只不过是一个前置校验和后置校验的问题,我个人倾向于在选择图片时就进行校验的,选择一些照片时,就应该在选择时阶段做安全判断的, 小程序端请求云函数方式// 图片转化buffer后,调用云函数 console.log(tempFiles); tempFiles.forEach(items => { console.log(items); // 图片转化buffer后,调用云函数 wx.getFileSystemManager().readFile({ filePath: items.path, success: res => { console.log(res); wx.cloud.callFunction({ // 小程序端请求imgSecCheck云函数,并传递img参数进行检验 name: 'imgSecCheck', data: { img: res.data } }) .then(res => { console.log(res); let { errCode } = res.result.data; switch(errCode) { case 87014: this.setData({ resultText: '内容含有违法违规内容' }) break; case 0: this.setData({ resultText: '内容OK' }) break; default: break; } }) .catch(err => { console.error(err); }) }, fail: err => { console.error(err); } }) }) // 还能再选几张图片 max = MAX_IMG_NUM - this.data.images.length this.setData({ selectPhoto: max <= 0 "text-align: center">至此,关于图片安全检测就已经完成了,您只需要根据检测的结果,做一些友好的用户提示,或者做一些自己的业务逻辑判断即可
常见问题
如何对上传的图片大小进行限制
有时候,您需要对用户上传图片的大小进行限制,限制用户任意上传超大图片,那怎么处理呢,在微信小程序里面,主要借助的是wx.chooseImage这个接口成功返回后临时路径的res.tempFiles中的size大小判断即可进行处理
具体实例代码如下所示
// 选择图片 onChooseImage() { // 还能再选几张图片,初始值设置最大的数量-当前的图片的长度 let max = MAX_IMG_NUM - this.data.images.length; wx.chooseImage({ count: max, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { console.log(res) const tempFiles = res.tempFiles; this.setData({ images: this.data.images.concat(res.tempFilePaths) // tempFilePath可以作为img标签的src属性显示图片 }) // 在选择图片时,对本地临时存储的图片,这个时候,进行图片的校验,当然你放在最后点击发布时,进行校验也是可以的,只不过是一个前置校验和后置校验的问题,我个人倾向于在选择图片时就进行校验的,选择一些照片时,就应该在选择时阶段做安全判断的, 小程序端请求云函数方式// 图片转化buffer后,调用云函数 console.log(tempFiles); tempFiles.forEach(items => { if (items && items.size > 1 * (1024 * 1024)) { // 限制图片的大小 wx.showToast({ icon: 'none', title: '上传的图片超过1M,禁止用户上传', duration: 4000 }) // 超过1M的图片,禁止用户上传 } console.log(items); // 图片转化buffer后,调用云函数 wx.getFileSystemManager().readFile({ filePath: items.path, success: res => { console.log(res); wx.cloud.callFunction({ // 请求调用云函数imgSecCheck name: 'imgSecCheck', data: { img: res.data } }) .then(res => { console.log(res); let { errCode } = res.result.data; switch(errCode) { case 87014: this.setData({ resultText: '内容含有违法违规内容' }) break; case 0: this.setData({ resultText: '内容OK' }) break; default: break; } }) .catch(err => { console.error(err); }) }, fail: err => { console.error(err); } }) }) // 还能再选几张图片 max = MAX_IMG_NUM - this.data.images.length this.setData({ selectPhoto: max <= 0 "text-align: center">注意: 使用微信官方的图片内容安全接口进行校验,限制图片大小限制:1M,否则的话就会报错
也就是说,对于超过1M大小的违规图片,微信官方提供的这个图片安全接口是无法进行校验的
这个根据自己的业务而定,在小程序端对用户上传图片的大小进行限制如果您觉得微信官方提供的图片安全接口满足不了自己的业务需求,那么可以选择一些其他的图片内容安全校验的接口的
这个图片安全校验是非常有必要的,用户一旦上传非法图片,一旦通过网络进行传播,产生了社会影响,平台是有责任的,这种前车之鉴是有的
如何解决多图上传覆盖的问题
对于上传图片来说,这个wx.cloud.uploadFileAPI接口只能上传一张图片,但是很多时候,是需要上传多张图片到云存储当中的,当点击发布的时候,我们是希望将多张图片都上传到云存储当中去的
这个API虽然只能每次上传一张,但您可以循环遍历多张图片,然后一张一张的上传的
在cloudPath上传文件的参数当中,它的值:需要注意:文件的名称
那如何保证上传的图片不被覆盖,文件不重名的情况下就不会被覆盖
而在选择图片的时候,不应该上传,因为用户可能有删除等操作,如果直接上传的话会造成资源的浪费
而应该在点发布按钮的时候,才执行上传操作,文件不重名覆盖的示例代码如下所示
let promiseArr = [] let fileIds = [] // 将图片的fileId存放到一个数组中 let imgLength = this.data.images.length; // 图片上传 for (let i = 0; i < imgLength; i++) { let p = new Promise((resolve, reject) => { let item = this.data.images[i] // 文件扩展名 let suffix = /\.\w+$/.exec(item)[0]; // 取文件后拓展名 wx.cloud.uploadFile({ // 利用官方提供的上传接口 cloudPath: 'blog/' + Date.now() + '-' + Math.random() * 1000000 + suffix, // 云存储路径,您也可以使用es6中的模板字符串进行拼接的 filePath: item, // 要上传文件资源的路径 success: (res) => { console.log(res); console.log(res.fileID) fileIds = fileIds.concat(res.fileID) // 将新上传的与之前上传的给拼接起来 resolve() }, fail: (err) => { console.error(err) reject() } }) }) promiseArr.push(p) } // 存入到云数据库,其中这个Promise.all(),等待里面所有的任务都执行之后,在去执行后面的任务,也就是等待上传所有的图片上传完后,才能把相对应的数据存到数据库当中,具体与promise相关问题,可自行查漏 Promise.all(promiseArr).then((res) => { db.collection('blog').add({ // 查找blog集合,将img,时间等数据添加到这个集合当中 data: { img: fileIds, createTime: db.serverDate(), // 服务端的时间 } }).then((res) => { console.log(res); this._hideToastTip(); this._successTip(); }) }) .catch((err) => { // 发布失败console.error(err); })上面通过利用当前时间+随机数的方式进行了一个区分,规避了上传文件同名的问题
因为这个上传接口,一次性只能上传一张图片,所以需要循环遍历图片,然后一张张的上传
一个是上传到云存储中,另一个是添加到云数据库集合当中,要分别注意下这两个操作,云数据库中的图片是从云存储中拿到的,然后再添加到云数据库当中去的
示例效果如下所示:
将上传的图片存储到云数据库中
注意:添加数据到云数据库中,需要手动创建集合,不然是无法上传不到云数据库当中的,会报错
至此,关于敏感图片的检测,以及多图片的上传到这里就已经完成了
如下是完整的小程序端逻辑示例代码
// miniprogram/pages/imgSecCheck/imgSecCheck.js // 最大上传图片数量 const MAX_IMG_NUM = 9; const db = wx.cloud.database() Page({ /** * 页面的初始数据 */ data: { images: [], selectPhoto: true, // 添加图片元素是否显示 }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { }, // 选择图片 onChooseImage() { // 还能再选几张图片,初始值设置最大的数量-当前的图片的长度 let max = MAX_IMG_NUM - this.data.images.length; wx.chooseImage({ count: max, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { console.log(res) const tempFiles = res.tempFiles; this.setData({ images: this.data.images.concat(res.tempFilePaths) // tempFilePath可以作为img标签的src属性显示图片 }) // 在选择图片时,对本地临时存储的图片,这个时候,进行图片的校验,当然你放在最后点击发布时,进行校验也是可以的,只不过是一个前置校验和后置校验的问题,我个人倾向于在选择图片时就进行校验的,选择一些照片时,就应该在选择时阶段做安全判断的, 小程序端请求云函数方式 // 图片转化buffer后,调用云函数 console.log(tempFiles); tempFiles.forEach(items => { if (items && items.size > 1 * (1024 * 1024)) { wx.showToast({ icon: 'none', title: '上传的图片超过1M,禁止用户上传', duration: 4000 }) // 超过1M的图片,禁止上传 } console.log(items); // 图片转化buffer后,调用云函数 wx.getFileSystemManager().readFile({ filePath: items.path, success: res => { console.log(res); this._checkImgSafe(res.data); // 检测图片安全校验 }, fail: err => { console.error(err); } }) }) // 还能再选几张图片 max = MAX_IMG_NUM - this.data.images.length this.setData({ selectPhoto: max <= 0 "htmlcode"><view class="image-list"> <!-- 显示图片 --> <block wx:for="{{images}}" wx:key="*this"> <view class="image-wrap"><image class="image" src="/UploadFiles/2021-04-02/{{item}}">您可以根据自己的业务逻辑需要,一旦检测到图片违规时,禁用按钮状态,或者给一些用户提示,都是可以的,在发布之前或者点击发布时,进行图片内容安全的校验都可以,一旦发现图片有违规时,就不让继续后面的操作的
结语
本文主要通过借助官方提供的图片security.imgSecCheck
接口,实现了对图片安全的校验,实现起来,是相当的方便的,对于基础性的校验,利用官方提供的这个接口,已经够用了的,但是如果想要更加严格的检测,可以引入一些第三方的内容安全强强校验,确保内容的安全
实现了如何对上传的图片大小进行限制,以及解决同名图片上传覆盖的问题
如果大家对文本内容安全校验以及图片安全校验仍然有什么问题,可以在下方留言,一起探讨。
公众号:腾讯云云开发
腾讯云云开发:https://cloudbase.net
云开发控制台:https://console.cloud.tencent.com/tcb"color: #ff0000">总结
DDR爱好者之家 Design By 杰米广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!DDR爱好者之家 Design By 杰米暂无评论...
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]