相比於文本的安全檢測,圖片的安全檢測要稍微略複雜一些,當您讀完本篇,將get到html
當用戶上傳敏感違規圖片時,禁止用戶上傳發布,而且作出相對應的用戶友好提示前端
一般,在校驗一張圖片是否含有違法違規內容相比於文本安全的校驗,一樣重要,有以下應用es6
在小程序開發中,提供了兩種方式數據庫
HTTPS 調用的請求接口地止json
https://api.weixin.qq.com/wxa/img_sec_check?access_token=ACCESS_TOKEN
檢測圖片審覈,根據官方文檔得知,須要兩個必傳的參數:分別是:access_token(接口調用憑證),media(要檢測的圖片文件)小程序
對於HTTPS調用方式,願意折騰的小夥伴能夠參考文本內容安全檢測(上篇)的處理方式,處理大同小異,本篇主要以雲開發的雲調用爲主微信小程序
對於wxml與wxss,你們能夠自行任意修改,本文重點在於圖片安全的校驗api
<view class="image-list"> <!-- 顯示圖片 --> <block wx:for="{{images}}" wx:key="*this"><view class="image-wrap"> <image class="image" src="{{item}}" mode="aspectFill" bind:tap="onPreviewImage" data-imgsrc="{{item}}"></image><i class="iconfont icon-shanchu" bind:tap="onDelImage" data-index="{{index}}"></i></view> </block> <!-- 選擇圖片 --> <view class="image-wrap selectphoto" hidden="{{!selectPhoto}}" bind:tap="onChooseImage"><i class="iconfont icon-add"></i></view> </view> <view class="footer"><button class="send-btn" bind:tap="send">發佈</button> </view>
對應的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方面可忽略,以下所示promise
對應的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 ? false : true // 當超過9張時,加號隱藏 }) }, }) }, // 點擊右上方刪除圖標,刪除圖片操做 onDelImage(event) { const index = event.target.dataset.index; // 點擊刪除當前圖片,用splice方法,刪除一張,從數組中移除一個 this.data.images.splice(index, 1) this.setData({ images: this.data.images }) // 當添加的圖片達到設置最大的數量時,添加按鈕隱藏,不讓新添加圖片 if (this.data.images.length == MAX_IMG_NUM - 1) { this.setData({ selectPhoto: true, }) } }, })
最終實現的前端UI效果以下所是:
您如今看到的效果,沒有任何雲函數代碼,只是前端的純靜態展現,對於一些涉嫌敏感圖片,是有必要進行作過濾處理的
在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 ? false : true // 當超過9張時,加號隱藏 }) }, }) }, // 刪除圖片 onDelImage(event) { const index = event.target.dataset.index; // 點擊刪除當前圖片,用splice方法,刪除一張,從數組中移除一個 this.data.images.splice(index, 1); this.setData({ images: this.data.images }) // 當添加的圖片達到設置最大的數量時,添加按鈕隱藏,不讓新添加圖片 if (this.data.images.length == MAX_IMG_NUM - 1) { this.setData({ selectPhoto: true, }) } }, })
示例效果以下所示:
至此,關於圖片安全檢測就已經完成了,您只須要根據檢測的結果,作一些友好的用戶提示,或者作一些本身的業務邏輯判斷便可
有時候,您須要對用戶上傳圖片的大小進行限制,限制用戶任意上傳超大圖片,那怎麼處理呢,在微信小程序裏面,主要藉助的是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 ? false : true // 當超過9張時,加號隱藏 }) }, }) },
注意: 使用微信官方的圖片內容安全接口進行校驗,限制圖片大小限制: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 ? false : true // 當超過9張時,加號隱藏 }) }, }) }, // 刪除圖片 onDelImage(event) { const index = event.target.dataset.index; // 點擊刪除當前圖片,用splice方法,刪除一張,從數組中移除一個 this.data.images.splice(index, 1); this.setData({ images: this.data.images }) // 當添加的圖片達到設置最大的數量時,添加按鈕隱藏,不讓新添加圖片 if (this.data.images.length == MAX_IMG_NUM - 1) { this.setData({ selectPhoto: true, }) } }, // 點擊發布按鈕,將圖片上傳到雲數據庫當中 send() { const images = this.data.images.length; if (images) { this._showToastTip(); let promiseArr = [] let fileIds = [] 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, 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(promiseArr).then((res) => { db.collection('blog').add({ // 查找blog集合,將數據添加到這個集合當中 data: { img: fileIds, createTime: db.serverDate(), // 服務端的時間 } }).then((res) => { console.log(res); this._hideToastTip(); this._successTip(); }) }) .catch((err) => { // 發佈失敗 console.error(err); }) } else { wx.showToast({ icon: 'none', title: '沒有選擇任何圖片,發佈不了', }) } }, // 校驗圖片的安全 _checkImgSafe(data) { wx.cloud.callFunction({ name: 'imgSecCheck', data: { img: 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); }) }, _showToastTip() { wx.showToast({ icon: 'none', title: '發佈中...', }) }, _hideToastTip() { wx.hideLoading(); }, _successTip() { wx.showToast({ icon: 'none', title: '發佈成功', }) }, })
完整的示例wxml,以下所示
<view class="image-list"> <!-- 顯示圖片 --> <block wx:for="{{images}}" wx:key="*this"> <view class="image-wrap"><image class="image" src="{{item}}" mode="aspectFill" bind:tap="onPreviewImage" data-imgsrc="{{item}}"></image><i class="iconfont icon-shanchu" bind:tap="onDelImage" data-index="{{index}}"></i> </view> </block> <!-- 選擇圖片 --> <view class="image-wrap selectphoto" hidden="{{!selectPhoto}}" bind:tap="onChooseImage"><i class="iconfont icon-add"></i></view> </view> <view class="footer"> <button class="send-btn" bind:tap="send">發佈</button> </view> <view> 檢測結果顯示: {{ resultText }} </view>
您能夠根據本身的業務邏輯須要,一旦檢測到圖片違規時,禁用按鈕狀態,或者給一些用戶提示,都是能夠的,在發佈以前或者點擊發布時,進行圖片內容安全的校驗均可以,一旦發現圖片有違規時,就不讓繼續後面的操做的
本文主要經過藉助官方提供的圖片security.imgSecCheck
接口,實現了對圖片安全的校驗,實現起來,是至關的方便的,對於基礎性的校驗,利用官方提供的這個接口,已經夠用了的,可是若是想要更加嚴格的檢測,能夠引入一些第三方的內容安全強強校驗,確保內容的安全
實現瞭如何對上傳的圖片大小進行限制,以及解決同名圖片上傳覆蓋的問題
若是你們對文本內容安全校驗以及圖片安全校驗仍然有什麼問題,能夠在下方留言,一塊兒探討。
公衆號:騰訊云云開發
騰訊云云開發:https://cloudbase.net
雲開發控制檯:https://console.cloud.tencent.com/tcb?from=12304
☁
更多精彩
掃描二維碼瞭解更多