用云開發(fā)Cloudbase實(shí)現(xiàn)小程序多圖片內(nèi)容安全監(jiān)測(cè)的代碼詳解
前言
相比于文本的安全檢測(cè),圖片的安全檢測(cè)要稍微略復(fù)雜一些,當(dāng)您讀完本篇,將get到
- 圖片安全檢測(cè)的應(yīng)用場(chǎng)景
- 解決圖片的安全校驗(yàn)的方式
- 使用云調(diào)用方式對(duì)圖片進(jìn)行檢測(cè)
- 如何對(duì)上傳圖片大小進(jìn)行限制
- 如何解決多圖上傳覆蓋問(wèn)題
示例效果
當(dāng)用戶上傳敏感違規(guī)圖片時(shí),禁止用戶上傳發(fā)布,并且做出相對(duì)應(yīng)的用戶友好提示

應(yīng)用場(chǎng)景
通常,在校驗(yàn)一張圖片是否含有違法違規(guī)內(nèi)容相比于文本安全的校驗(yàn),同樣重要,有如下應(yīng)用
圖片智能鑒黃:涉及拍照的工具類應(yīng)用(如美拍,識(shí)圖類應(yīng)用)用戶拍照上傳檢測(cè);電商類商品上架圖片檢測(cè);媒體類用戶文章里的圖片檢測(cè)等敏感人臉識(shí)別:用戶頭像;媒體類用戶文章里的圖片檢測(cè);社交類用戶上傳的圖片檢測(cè)等,凡是有用戶自發(fā)生產(chǎn)內(nèi)容的都應(yīng)當(dāng)提前做檢測(cè)
解決圖片的安全手段
在小程序開發(fā)中,提供了兩種方式
- HTTPS調(diào)用
- 云調(diào)用
HTTPS 調(diào)用的請(qǐng)求接口地止
https://api.weixin.qq.com/wxa/img_sec_check?access_token=ACCESS_TOKEN
檢測(cè)圖片審核,根據(jù)官方文檔得知,需要兩個(gè)必傳的參數(shù):分別是:access_token(接口調(diào)用憑證),media(要檢測(cè)的圖片文件)
對(duì)于HTTPS調(diào)用方式,愿意折騰的小伙伴可以參考文本內(nèi)容安全檢測(cè)(上篇)的處理方式,處理大同小異,本篇主要以云開發(fā)的云調(diào)用為主
功能實(shí)現(xiàn):小程序端邏輯
對(duì)于wxml與wxss,大家可以自行任意修改,本文重點(diǎn)在于圖片安全的校驗(yàn)
<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">發(fā)布</button>
</view>
對(duì)應(yīng)的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;
}
最終呈現(xiàn)的UI,由于只是用于圖片檢測(cè)演示,UI方面可忽略,如下所示

對(duì)應(yīng)的JS代碼
/*
* 涉及到的API:wx.chooseImage 從本地相冊(cè)選擇圖片或使用相機(jī)拍照
*(https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.chooseImage.html)
*
*
*/// 最大上傳圖片數(shù)量
const MAX_IMG_NUM = 9;
const db = wx.cloud.database(); // 初始化云數(shù)據(jù)庫(kù)
Page({
/**
* 頁(yè)面的初始數(shù)據(jù)
*/
data: {
images: [], // 把上傳的圖片存放在一個(gè)數(shù)組對(duì)象里面
selectPhoto: true, // 添加+icon元素是否顯示
},
/**
* 生命周期函數(shù)--監(jiān)聽頁(yè)面加載
*/
onLoad: function (options) {
},
// 選擇圖片
onChooseImage() {
// 還能再選幾張圖片,初始值設(shè)置最大的數(shù)量-當(dāng)前的圖片的長(zhǎng)度
let max = MAX_IMG_NUM - this.data.images.length;
wx.chooseImage({
count: max, // count表示最多可以選擇的圖片張數(shù)
sizeType: ['original', 'compressed'], // 所選的圖片的尺寸
sourceType: ['album', 'camera'], // 選擇圖片的來(lái)源
success: (res) => { // 接口調(diào)用成功的回調(diào)函數(shù)console.log(res)
this.setData({ // tempFilePath可以作為img標(biāo)簽的src屬性顯示圖片,下面是將后添加的圖片與之前的圖片給追加起來(lái)
images: this.data.images.concat(res.tempFilePaths)
})
// 還能再選幾張圖片
max = MAX_IMG_NUM - this.data.images.length
this.setData({
selectPhoto: max <= 0 ? false : true // 當(dāng)超過(guò)9張時(shí),加號(hào)隱藏
})
},
})
},
// 點(diǎn)擊右上方刪除圖標(biāo),刪除圖片操作
onDelImage(event) {
const index = event.target.dataset.index;
// 點(diǎn)擊刪除當(dāng)前圖片,用splice方法,刪除一張,從數(shù)組中移除一個(gè)
this.data.images.splice(index, 1)
this.setData({
images: this.data.images
})
// 當(dāng)添加的圖片達(dá)到設(shè)置最大的數(shù)量時(shí),添加按鈕隱藏,不讓新添加圖片
if (this.data.images.length == MAX_IMG_NUM - 1) {
this.setData({
selectPhoto: true,
})
}
},
})
最終實(shí)現(xiàn)的前端UI效果如下所是:

您現(xiàn)在看到的效果,沒有任何云函數(shù)代碼,只是前端的純靜態(tài)展示,對(duì)于一些涉嫌敏感圖片,是有必要進(jìn)行做過(guò)濾處理的
功能實(shí)現(xiàn):云函數(shù)側(cè)邏輯
在cloudfunctions目錄文件夾下創(chuàng)建云函數(shù)imgSecCheck

并在該目錄下創(chuàng)建config.json,配置參數(shù)如下所示
{
"permissions": {
"openapi": [
"security.imgSecCheck"
]
}
}
配置完后,在主入口index.js中,如下所示,通過(guò)security.imgSecCheck接口,并傳入media對(duì)象
// 云函數(shù)入口文件
const cloud = require('wx-server-sdk');
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})
// 云函數(shù)入口函數(shù)
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) // 這里必須要將小程序端傳過(guò)來(lái)的進(jìn)行Buffer轉(zhuǎn)化,否則就會(huì)報(bào)錯(cuò),接口異常
}
})
if (result && result.errCode.toString() === '87014') {
return { code: 500, msg: '內(nèi)容含有違法違規(guī)內(nèi)容', data: result }
} else {
return { code: 200, msg: '內(nèi)容ok', data: result }
}
} catch (err) {
// 錯(cuò)誤處理
if (err.errCode.toString() === '87014') {
return { code: 500, msg: '內(nèi)容含有違法違規(guī)內(nèi)容', data: err }
}
return { code: 502, msg: '調(diào)用imgSecCheck接口異常', data: err }
}
}
您會(huì)發(fā)現(xiàn)在云函數(shù)端,就這么幾行代碼,就完成了圖片安全校驗(yàn)
而在小程序端,代碼如下所示
// miniprogram/pages/imgSecCheck/imgSecCheck.js
// 最大上傳圖片數(shù)量
const MAX_IMG_NUM = 9;
const db = wx.cloud.database()
Page({
/**
* 頁(yè)面的初始數(shù)據(jù)
*/
data: {
images: [],
selectPhoto: true, // 添加圖片元素是否顯示
},
/**
* 生命周期函數(shù)--監(jiān)聽頁(yè)面加載
*/
onLoad: function (options) {
},
// 選擇圖片
onChooseImage() {
// const that = this; // 如果下面用了箭頭函數(shù),那么這行代碼是不需要的,直接用this就可以了的// 還能再選幾張圖片,初始值設(shè)置最大的數(shù)量-當(dāng)前的圖片的長(zhǎng)度
let max = MAX_IMG_NUM - this.data.images.length;
wx.chooseImage({
count: max,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: (res) => { // 這里若不是箭頭函數(shù),那么下面的this.setData的this要換成that上面的臨時(shí)變量,作用域的問(wèn)題,不清楚的,可以看下this指向相關(guān)的知識(shí)
console.log(res)
// tempFilePath可以作為img標(biāo)簽的src屬性顯示圖片
const tempFiles = res.tempFiles;
this.setData({
images: this.data.images.concat(res.tempFilePaths)
})
// 在選擇圖片時(shí),對(duì)本地臨時(shí)存儲(chǔ)的圖片,這個(gè)時(shí)候,進(jìn)行圖片的校驗(yàn),當(dāng)然你放在最后點(diǎn)擊發(fā)布時(shí),進(jìn)行校驗(yàn)也是可以的,只不過(guò)是一個(gè)前置校驗(yàn)和后置校驗(yàn)的問(wèn)題,我個(gè)人傾向于在選擇圖片時(shí)就進(jìn)行校驗(yàn)的,選擇一些照片時(shí),就應(yīng)該在選擇時(shí)階段做安全判斷的, 小程序端請(qǐng)求云函數(shù)方式// 圖片轉(zhuǎn)化buffer后,調(diào)用云函數(shù)
console.log(tempFiles);
tempFiles.forEach(items => {
console.log(items);
// 圖片轉(zhuǎn)化buffer后,調(diào)用云函數(shù)
wx.getFileSystemManager().readFile({
filePath: items.path,
success: res => {
console.log(res);
wx.cloud.callFunction({ // 小程序端請(qǐng)求imgSecCheck云函數(shù),并傳遞img參數(shù)進(jìn)行檢驗(yàn)
name: 'imgSecCheck',
data: {
img: res.data
}
})
.then(res => {
console.log(res);
let { errCode } = res.result.data;
switch(errCode) {
case 87014:
this.setData({
resultText: '內(nèi)容含有違法違規(guī)內(nèi)容'
})
break;
case 0:
this.setData({
resultText: '內(nèi)容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 // 當(dāng)超過(guò)9張時(shí),加號(hào)隱藏
})
},
})
},
// 刪除圖片
onDelImage(event) {
const index = event.target.dataset.index;
// 點(diǎn)擊刪除當(dāng)前圖片,用splice方法,刪除一張,從數(shù)組中移除一個(gè)
this.data.images.splice(index, 1);
this.setData({
images: this.data.images
})
// 當(dāng)添加的圖片達(dá)到設(shè)置最大的數(shù)量時(shí),添加按鈕隱藏,不讓新添加圖片
if (this.data.images.length == MAX_IMG_NUM - 1) {
this.setData({
selectPhoto: true,
})
}
},
})
示例效果如下所示:

至此,關(guān)于圖片安全檢測(cè)就已經(jīng)完成了,您只需要根據(jù)檢測(cè)的結(jié)果,做一些友好的用戶提示,或者做一些自己的業(yè)務(wù)邏輯判斷即可
常見問(wèn)題
如何對(duì)上傳的圖片大小進(jìn)行限制
有時(shí)候,您需要對(duì)用戶上傳圖片的大小進(jìn)行限制,限制用戶任意上傳超大圖片,那怎么處理呢,在微信小程序里面,主要借助的是wx.chooseImage這個(gè)接口成功返回后臨時(shí)路徑的res.tempFiles中的size大小判斷即可進(jìn)行處理

具體實(shí)例代碼如下所示
// 選擇圖片
onChooseImage() {
// 還能再選幾張圖片,初始值設(shè)置最大的數(shù)量-當(dāng)前的圖片的長(zhǎng)度
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標(biāo)簽的src屬性顯示圖片
})
// 在選擇圖片時(shí),對(duì)本地臨時(shí)存儲(chǔ)的圖片,這個(gè)時(shí)候,進(jìn)行圖片的校驗(yàn),當(dāng)然你放在最后點(diǎn)擊發(fā)布時(shí),進(jìn)行校驗(yàn)也是可以的,只不過(guò)是一個(gè)前置校驗(yàn)和后置校驗(yàn)的問(wèn)題,我個(gè)人傾向于在選擇圖片時(shí)就進(jìn)行校驗(yàn)的,選擇一些照片時(shí),就應(yīng)該在選擇時(shí)階段做安全判斷的, 小程序端請(qǐng)求云函數(shù)方式// 圖片轉(zhuǎn)化buffer后,調(diào)用云函數(shù)
console.log(tempFiles);
tempFiles.forEach(items => {
if (items && items.size > 1 * (1024 * 1024)) { // 限制圖片的大小
wx.showToast({
icon: 'none',
title: '上傳的圖片超過(guò)1M,禁止用戶上傳',
duration: 4000
})
// 超過(guò)1M的圖片,禁止用戶上傳
}
console.log(items);
// 圖片轉(zhuǎn)化buffer后,調(diào)用云函數(shù)
wx.getFileSystemManager().readFile({
filePath: items.path,
success: res => {
console.log(res);
wx.cloud.callFunction({ // 請(qǐng)求調(diào)用云函數(shù)imgSecCheck
name: 'imgSecCheck',
data: {
img: res.data
}
})
.then(res => {
console.log(res);
let { errCode } = res.result.data;
switch(errCode) {
case 87014:
this.setData({
resultText: '內(nèi)容含有違法違規(guī)內(nèi)容'
})
break;
case 0:
this.setData({
resultText: '內(nèi)容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 // 當(dāng)超過(guò)9張時(shí),加號(hào)隱藏
})
},
})
},

注意: 使用微信官方的圖片內(nèi)容安全接口進(jìn)行校驗(yàn),限制圖片大小限制:1M,否則的話就會(huì)報(bào)錯(cuò)

也就是說(shuō),對(duì)于超過(guò)1M大小的違規(guī)圖片,微信官方提供的這個(gè)圖片安全接口是無(wú)法進(jìn)行校驗(yàn)的
這個(gè)根據(jù)自己的業(yè)務(wù)而定,在小程序端對(duì)用戶上傳圖片的大小進(jìn)行限制如果您覺得微信官方提供的圖片安全接口滿足不了自己的業(yè)務(wù)需求,那么可以選擇一些其他的圖片內(nèi)容安全校驗(yàn)的接口的
這個(gè)圖片安全校驗(yàn)是非常有必要的,用戶一旦上傳非法圖片,一旦通過(guò)網(wǎng)絡(luò)進(jìn)行傳播,產(chǎn)生了社會(huì)影響,平臺(tái)是有責(zé)任的,這種前車之鑒是有的
如何解決多圖上傳覆蓋的問(wèn)題
對(duì)于上傳圖片來(lái)說(shuō),這個(gè)wx.cloud.uploadFileAPI接口只能上傳一張圖片,但是很多時(shí)候,是需要上傳多張圖片到云存儲(chǔ)當(dāng)中的,當(dāng)點(diǎn)擊發(fā)布的時(shí)候,我們是希望將多張圖片都上傳到云存儲(chǔ)當(dāng)中去的
這個(gè)API雖然只能每次上傳一張,但您可以循環(huán)遍歷多張圖片,然后一張一張的上傳的
在cloudPath上傳文件的參數(shù)當(dāng)中,它的值:需要注意:文件的名稱
那如何保證上傳的圖片不被覆蓋,文件不重名的情況下就不會(huì)被覆蓋
而在選擇圖片的時(shí)候,不應(yīng)該上傳,因?yàn)橛脩艨赡苡袆h除等操作,如果直接上傳的話會(huì)造成資源的浪費(fèi)
而應(yīng)該在點(diǎn)發(fā)布按鈕的時(shí)候,才執(zhí)行上傳操作,文件不重名覆蓋的示例代碼如下所示
let promiseArr = []
let fileIds = [] // 將圖片的fileId存放到一個(gè)數(shù)組中
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]
// 文件擴(kuò)展名
let suffix = /\.\w+$/.exec(item)[0]; // 取文件后拓展名
wx.cloud.uploadFile({ // 利用官方提供的上傳接口
cloudPath: 'blog/' + Date.now() + '-' + Math.random() * 1000000 + suffix, // 云存儲(chǔ)路徑,您也可以使用es6中的模板字符串進(jìn)行拼接的
filePath: item, // 要上傳文件資源的路徑
success: (res) => {
console.log(res);
console.log(res.fileID)
fileIds = fileIds.concat(res.fileID) // 將新上傳的與之前上傳的給拼接起來(lái)
resolve()
},
fail: (err) => {
console.error(err)
reject()
}
})
})
promiseArr.push(p)
}
// 存入到云數(shù)據(jù)庫(kù),其中這個(gè)Promise.all(),等待里面所有的任務(wù)都執(zhí)行之后,在去執(zhí)行后面的任務(wù),也就是等待上傳所有的圖片上傳完后,才能把相對(duì)應(yīng)的數(shù)據(jù)存到數(shù)據(jù)庫(kù)當(dāng)中,具體與promise相關(guān)問(wèn)題,可自行查漏
Promise.all(promiseArr).then((res) => {
db.collection('blog').add({ // 查找blog集合,將img,時(shí)間等數(shù)據(jù)添加到這個(gè)集合當(dāng)中
data: {
img: fileIds,
createTime: db.serverDate(), // 服務(wù)端的時(shí)間
}
}).then((res) => {
console.log(res);
this._hideToastTip();
this._successTip();
})
})
.catch((err) => {
// 發(fā)布失敗console.error(err);
})
上面通過(guò)利用當(dāng)前時(shí)間+隨機(jī)數(shù)的方式進(jìn)行了一個(gè)區(qū)分,規(guī)避了上傳文件同名的問(wèn)題
因?yàn)檫@個(gè)上傳接口,一次性只能上傳一張圖片,所以需要循環(huán)遍歷圖片,然后一張張的上傳
一個(gè)是上傳到云存儲(chǔ)中,另一個(gè)是添加到云數(shù)據(jù)庫(kù)集合當(dāng)中,要分別注意下這兩個(gè)操作,云數(shù)據(jù)庫(kù)中的圖片是從云存儲(chǔ)中拿到的,然后再添加到云數(shù)據(jù)庫(kù)當(dāng)中去的
示例效果如下所示:


將上傳的圖片存儲(chǔ)到云數(shù)據(jù)庫(kù)中
注意:添加數(shù)據(jù)到云數(shù)據(jù)庫(kù)中,需要手動(dòng)創(chuàng)建集合,不然是無(wú)法上傳不到云數(shù)據(jù)庫(kù)當(dāng)中的,會(huì)報(bào)錯(cuò)

至此,關(guān)于敏感圖片的檢測(cè),以及多圖片的上傳到這里就已經(jīng)完成了
如下是完整的小程序端邏輯示例代碼
// miniprogram/pages/imgSecCheck/imgSecCheck.js
// 最大上傳圖片數(shù)量
const MAX_IMG_NUM = 9;
const db = wx.cloud.database()
Page({
/**
* 頁(yè)面的初始數(shù)據(jù)
*/
data: {
images: [],
selectPhoto: true, // 添加圖片元素是否顯示
},
/**
* 生命周期函數(shù)--監(jiān)聽頁(yè)面加載
*/
onLoad: function (options) {
},
// 選擇圖片
onChooseImage() {
// 還能再選幾張圖片,初始值設(shè)置最大的數(shù)量-當(dāng)前的圖片的長(zhǎng)度
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標(biāo)簽的src屬性顯示圖片
})
// 在選擇圖片時(shí),對(duì)本地臨時(shí)存儲(chǔ)的圖片,這個(gè)時(shí)候,進(jìn)行圖片的校驗(yàn),當(dāng)然你放在最后點(diǎn)擊發(fā)布時(shí),進(jìn)行校驗(yàn)也是可以的,只不過(guò)是一個(gè)前置校驗(yàn)和后置校驗(yàn)的問(wèn)題,我個(gè)人傾向于在選擇圖片時(shí)就進(jìn)行校驗(yàn)的,選擇一些照片時(shí),就應(yīng)該在選擇時(shí)階段做安全判斷的, 小程序端請(qǐng)求云函數(shù)方式
// 圖片轉(zhuǎn)化buffer后,調(diào)用云函數(shù)
console.log(tempFiles);
tempFiles.forEach(items => {
if (items && items.size > 1 * (1024 * 1024)) {
wx.showToast({
icon: 'none',
title: '上傳的圖片超過(guò)1M,禁止用戶上傳',
duration: 4000
})
// 超過(guò)1M的圖片,禁止上傳
}
console.log(items);
// 圖片轉(zhuǎn)化buffer后,調(diào)用云函數(shù)
wx.getFileSystemManager().readFile({
filePath: items.path,
success: res => {
console.log(res);
this._checkImgSafe(res.data); // 檢測(cè)圖片安全校驗(yàn)
},
fail: err => {
console.error(err);
}
})
})
// 還能再選幾張圖片
max = MAX_IMG_NUM - this.data.images.length
this.setData({
selectPhoto: max <= 0 ? false : true // 當(dāng)超過(guò)9張時(shí),加號(hào)隱藏
})
},
})
},
// 刪除圖片
onDelImage(event) {
const index = event.target.dataset.index;
// 點(diǎn)擊刪除當(dāng)前圖片,用splice方法,刪除一張,從數(shù)組中移除一個(gè)
this.data.images.splice(index, 1);
this.setData({
images: this.data.images
})
// 當(dāng)添加的圖片達(dá)到設(shè)置最大的數(shù)量時(shí),添加按鈕隱藏,不讓新添加圖片
if (this.data.images.length == MAX_IMG_NUM - 1) {
this.setData({
selectPhoto: true,
})
}
},
// 點(diǎn)擊發(fā)布按鈕,將圖片上傳到云數(shù)據(jù)庫(kù)當(dāng)中
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]
// 文件擴(kuò)展名
let suffix = /\.\w+$/.exec(item)[0]; // 取文件后拓展名
wx.cloud.uploadFile({ // 上傳圖片至云存儲(chǔ),循環(huán)遍歷,一張張的上傳
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)
}
// 存入到云數(shù)據(jù)庫(kù)
Promise.all(promiseArr).then((res) => {
db.collection('blog').add({ // 查找blog集合,將數(shù)據(jù)添加到這個(gè)集合當(dāng)中
data: {
img: fileIds,
createTime: db.serverDate(), // 服務(wù)端的時(shí)間
}
}).then((res) => {
console.log(res);
this._hideToastTip();
this._successTip();
})
})
.catch((err) => {
// 發(fā)布失敗
console.error(err);
})
} else {
wx.showToast({
icon: 'none',
title: '沒有選擇任何圖片,發(fā)布不了',
})
}
},
// 校驗(yàn)圖片的安全
_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: '內(nèi)容含有違法違規(guī)內(nèi)容'
})
break;
case 0:
this.setData({
resultText: '內(nèi)容OK'
})
break;
default:
break;
}
})
.catch(err => {
console.error(err);
})
},
_showToastTip() {
wx.showToast({
icon: 'none',
title: '發(fā)布中...',
})
},
_hideToastTip() {
wx.hideLoading();
},
_successTip() {
wx.showToast({
icon: 'none',
title: '發(fā)布成功',
})
},
})
完整的示例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">發(fā)布</button>
</view>
<view>
檢測(cè)結(jié)果顯示: {{ resultText }}
</view>
您可以根據(jù)自己的業(yè)務(wù)邏輯需要,一旦檢測(cè)到圖片違規(guī)時(shí),禁用按鈕狀態(tài),或者給一些用戶提示,都是可以的,在發(fā)布之前或者點(diǎn)擊發(fā)布時(shí),進(jìn)行圖片內(nèi)容安全的校驗(yàn)都可以,一旦發(fā)現(xiàn)圖片有違規(guī)時(shí),就不讓繼續(xù)后面的操作的
結(jié)語(yǔ)
本文主要通過(guò)借助官方提供的圖片security.imgSecCheck
接口,實(shí)現(xiàn)了對(duì)圖片安全的校驗(yàn),實(shí)現(xiàn)起來(lái),是相當(dāng)?shù)姆奖愕?對(duì)于基礎(chǔ)性的校驗(yàn),利用官方提供的這個(gè)接口,已經(jīng)夠用了的,但是如果想要更加嚴(yán)格的檢測(cè),可以引入一些第三方的內(nèi)容安全強(qiáng)強(qiáng)校驗(yàn),確保內(nèi)容的安全
實(shí)現(xiàn)了如何對(duì)上傳的圖片大小進(jìn)行限制,以及解決同名圖片上傳覆蓋的問(wèn)題
如果大家對(duì)文本內(nèi)容安全校驗(yàn)以及圖片安全校驗(yàn)仍然有什么問(wèn)題,可以在下方留言,一起探討。
公眾號(hào):騰訊云云開發(fā)
騰訊云云開發(fā):https://cloudbase.net
云開發(fā)控制臺(tái):https://console.cloud.tencent.com/tcb?from=12304
總結(jié)
到此這篇關(guān)于用云開發(fā)Cloudbase實(shí)現(xiàn)小程序多圖片內(nèi)容安全監(jiān)測(cè)的文章就介紹到這了,更多相關(guān)小程序云開發(fā)多圖片內(nèi)容安全檢測(cè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js通過(guò)classname來(lái)獲取元素的方法
下面小編就為大家?guī)?lái)一篇js通過(guò)classname來(lái)獲取元素的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起 小編過(guò)來(lái)看看吧2016-11-11
JavaScript驗(yàn)證18位身份證號(hào)碼最后一位正確性的實(shí)現(xiàn)代碼
這篇文章主要介紹了JavaScript驗(yàn)證18位身份證號(hào)碼最后一位正確性的實(shí)現(xiàn)代碼,小編親測(cè)有效,需要的朋友可以參考下2014-08-08
自動(dòng)刷新網(wǎng)頁(yè),自動(dòng)刷新當(dāng)前頁(yè)面,JS調(diào)用
自動(dòng)刷新網(wǎng)頁(yè),自動(dòng)刷新當(dāng)前頁(yè)面,JS調(diào)用,需要的朋友可以參考一下2013-06-06
javascript簡(jiǎn)單寫的判斷電話號(hào)碼實(shí)例
這篇文章主要介紹了javascript簡(jiǎn)單寫的判斷電話號(hào)碼實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-05-05
js 第二代身份證號(hào)碼的驗(yàn)證機(jī)制代碼
在盛大某網(wǎng)站注冊(cè)的時(shí)候,身份證必填,但我又不想填真實(shí)身份證號(hào)碼,于是隨便編了串自認(rèn)為合法的身份證號(hào)碼,但是卻馬上被提示號(hào)碼錯(cuò)誤2011-05-05
javascript實(shí)現(xiàn)QQ空間相冊(cè)展示源碼
本文給大家分享基于javascript制作的qq空間相冊(cè)展示效果,涉及到html\css布局思維,浮動(dòng)定位詳解,具體實(shí)現(xiàn)代碼大家參考下本文2017-12-12
給頁(yè)面渲染時(shí)間加速 干掉Dom Level 0 Event
我們?nèi)サ羰录壎ǖ倪壿?發(fā)現(xiàn)只渲染dom元素,不綁定事件的時(shí)間,僅僅125ms,可見事件綁定的時(shí)間消耗還是很大的 ,尤其是第一種方式,也就是Dom Level 0 Event,最為耗時(shí)2012-12-12
javascript中undefined的本質(zhì)解析
這篇文章主要介紹了javascript中undefined的本質(zhì)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07

