此次分享下「發帖功能」,這個功能其實風險蠻大的,特別是對一些敏感言論的控制,若是沒有作好可能致使小程序被封,因此除了必要的人工審覈和巡查之外,咱們須要一些微信安全監測API的幫忙,在AI加持下,如今不少大公司對內容和圖片的效率大大提升了。html
這個DEMO僅是一個流程示例,因爲涉及到雲函數和「真」敏感圖,這裏就有文字圖代替。
node
發帖的功能只要理清思路,其實並不複雜,利用機器AI作內容審查是關鍵,直接關係到小程序的總體安全。json
[toc]小程序
let tempImg = 0; //表明已選擇的圖片 wx.chooseImage({ count: 3 - tempImg.length, //選擇不超過3張照片,去掉當前已經選擇的照片 sizeType: ['original', 'compressed'], //獲取原圖或者壓縮圖 sourceType: ['album', 'camera'], //獲取圖片來源 圖庫、拍照 success(res) { // tempFilePath能夠做爲img標籤的src屬性顯示圖片 let tempFilePaths = res.tempFilePaths; console.log(tempFilePaths); //舉例:這裏能夠size 來判斷圖片是否大於 1MB,方便後面內容檢查 if (res.tempFiles[0] && res.tempFiles[0].size > 1024 * 1024) { console.log("圖片大於1MB啦") } } })
這裏用到的方法是chooseImage,它能夠設置讓用戶選擇手機圖片庫和拍照得到,須要注意的是考慮到後面要用微信自帶API作圖片安全檢查,圖片大小不能超過1MB,因此須要設置sizeType爲compressed。segmentfault
因爲內容安全對於小程序運營相當重要,稍有不慎就容易致使小程序被封,因此在這塊的校驗除了常規人工檢查外,咱們還能夠用到微信的內容安全API。api
爲何用微信官方提供的API?
主要有二點:有必定的免費額度,基於企鵝大廠的專業AI檢查。安全
目錄結構服務器
├─checkContent │ config.json //雲調用的權限配置 │ index.js //雲服務器node 入口文件 │ package-lock.json │ package.json // NPM包依賴 │ ...
爲何要強調這個?
由於本人一開始在用雲函數+雲調用的時候,常常會出現各類不明BUG,不少都是由於目錄裏面少傳文件,或者少配置。微信
雲函數內容:app
const cloud = require('wx-server-sdk'); cloud.init(); exports.main = async (event, context) => { console.log(event.txt); const { value, txt } = event; try { let msgR = false; let imageR = false; //檢查 文字內容是否違規 if (txt) { msgR = await cloud.openapi.security.msgSecCheck({ content: txt }) } //檢查 圖片內容是否違規 if (value) { imageR = await cloud.openapi.security.imgSecCheck({ media: { header: { 'Content-Type': 'application/octet-stream' }, contentType: 'image/png', value: Buffer.from(value) } }) } return { msgR, //內容檢查返回值 imageR //圖片檢查返回值 }; } catch (err) { // 錯誤處理 // err.errCode !== 0 return err } }
這裏主要用到security.msgSecCheck和security.imgSecCheck這2個微信開放雲調用方法(需開發者工具版本 >= 1.02.1904090),以往咱們還要在服務器上單獨寫個方法,如今變得十分的方便,直接在雲函數中調用便可。
這裏須要重點說2個點
{ "permissions": { "openapi": [ "security.msgSecCheck", "security.imgSecCheck" ] } }
wx.cloud.callFunction({ name: 'checkContent', data: { txt: "樂於分享,一塊兒進步" }, success(_res) { console.log(_res) }, fail(_res) { console.log(_res) } }) //返回值參考 { "errMsg": "cloud.callFunction:ok", "result": { "msgR": { "errMsg": "openapi.security.msgSecCheck:ok", "errCode": 0 }, "imageR": false }, "requestID": "77952319-b2b4-11e9-bdc8-525400192d0e" }
應用場景舉例:
經過wx.cloud.callFunction的方法調用checkContent的雲函數,檢查一段文本是否含有違法違規內容。
//獲取 temp臨時圖片文件的 buffer wx.getFileSystemManager().readFile({ filePath: tempImg[0], //這裏作示例,因此就選取第一張圖片 success: buffer => { console.log(buffer.data) //這裏是 雲函數調用方法 wx.cloud.callFunction({ name: 'checkContent', data: { value: buffer.data }, success(json) { console.log(json.result.imageR) if (json.result.imageR.errCode == 87014) { wx.showToast({ title: '圖片含有違法違規內容', icon: 'none' }); console.log("bad") } else { //圖片正常 } } }) } }) //返回值參考 { "errMsg": "cloud.callFunction:ok", "result": { "msgR": false, "imageR": { "errMsg": "openapi.security.imgSecCheck:ok", "errCode": 0 } }, "requestID": "c126353c2d-b40b-11e9-81c4d-525400235f2a" }
應用場景舉例:
圖片智能鑑黃:涉及拍照的工具類應用(如美拍,識圖類應用)用戶拍照上傳檢測;電商類商品上架圖片檢測;媒體類用戶文章裏的圖片檢測等;
敏感人臉識別:用戶頭像;媒體類用戶文章裏的圖片檢測;社交類用戶上傳的圖片檢測等。 頻率限制:單個 appId 調用上限爲 2000 次/分鐘,200,000 次/天*(圖片大小限制:1M)
這裏先要用 getFileSystemManager() 獲取臨時圖片的buffer(這個是重點),而後再經過wx.cloud.callFunction的方法調用 checkContent的雲函數中security.imgSecCheck的方法,校驗一張圖片是否含有違法違規內容。
一開始本人調試的時候,也遇到沒法上傳的問題,必須經過文件管理(getFileSystemManager)獲取buffer後才能上傳檢查圖片,耗費了本人很多debugger時間。
本來想作個實際的demo(代碼片斷)分享給你們打開參考的,可是雲函數必須是一個已註冊的APPID,無奈只能貼代碼。
這裏主要仍是提供一個總體思路,但願能幫助你們減小開發成本,更好的解決問題和完成任務 ^_^
html部分:
<!-- pages/post /index.wxml --> <view class="wrap"> <view class="title"> <input placeholder="智酷方程式,樂於分享" maxlength="30" bindinput="getTitle"/> </view> <view class="content"> <textarea auto-focus="true" maxlength="200" bindinput="textareaCtrl" placeholder-style="color:#999;" placeholder="關注公衆號,一塊兒學習,一塊兒進步" /> <view class='fontNum'>{{content.length}}/200</view> </view> <view class="chooseImg"> <block wx:for="{{tempImg}}" wx:for-item="item" wx:key="ids" wx:for-index="index"> <view class="chooseImgBox"> <image src="{{item}}" /> <view data-index="{{index}}" catch:tap="removeImg" class="removeImg"></view> </view> </block> <!-- 判斷圖片 大於等於3張的時候 取消 更多 --> <block wx:if="{{tempImg.length < 3}}"> <view class="chooseImgBoxMore" catch:tap="choosePhoto"> <view class="arrow"></view> </view> </block> </view> <view class='submit' catch:tap="submitPost"> <view class='blue'>提交</view> <view>取消</view> </view> </view>
JS部分:
Page({ /** * 頁面的初始數據 */ data: { titleDetail: "", //帖子title內容 content: "", //發帖內容 tempImg: [], //選擇圖片的縮略圖,臨時地址 }, /** * 生命週期函數--監聽頁面加載 */ onLoad: function (options) { wx.cloud.init(); }, /** * 生命週期函數--監聽頁面顯示 */ onShow: function () { }, /** * 檢測輸入字數 * @param {object} e */ textareaCtrl: function (e) { if (e.detail.value) { this.setData({ content: e.detail.value }) } else { this.setData({ content: "" }) } }, /** * 選擇圖片 */ choosePhoto() { let self = this; let tempImg = self.data.tempImg; if (tempImg.length > 2) { return; } wx.chooseImage({ count: 3 - tempImg.length, //選擇不超過3張照片,去掉當前已經選擇的照片 sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success(res) { console.log(res); // tempFilePath能夠做爲img標籤的src屬性顯示圖片 let tempFilePaths = res.tempFilePaths; tempImg = tempImg.concat(tempFilePaths); console.log(tempImg); self.setData({ tempImg }) wx.getFileSystemManager().readFile({ filePath: tempImg[0], success: buffer => { console.log(buffer.data) wx.cloud.callFunction({ name: 'checkContent', data: { value: buffer.data }, success(json) { console.log(JSON.stringify(json)) console.log(json.result.imageR) if (json.result.imageR.errCode == 87014) { wx.showToast({ title: '圖片含有違法違規內容', icon: 'none' }); console.log("bad") } else { //圖片正常 } } }) } }) }, fail: err => { console.log(err) } }) }, /** * 刪除照片 */ removeImg(e) { let self = this; let index = e.currentTarget.dataset.index; console.log(e); let tempImg = self.data.tempImg; tempImg.splice(index, 1); self.setData({ tempImg }) }, /** * 發貼 */ submitPost(e) { let { titleDetail, content } = this.data; wx.cloud.callFunction({ name: 'checkContent', data: { txt: content }, success(_res) { console.log(JSON.stringify(_res)) wx.navigateTo({ url: "/pages/postimg/result" }) }, fail(_res) { console.log(_res) } }) } })
往期回顧:
[[[打怪升級]小程序評論回覆和發貼功能實戰(一)](https://segmentfault.com/a/11...
[[填坑手冊]小程序Canvas生成海報(一)](https://segmentfault.com/a/11...
[[拆彈時刻]小程序Canvas生成海報(二)](https://segmentfault.com/a/11...
[[填坑手冊]小程序目錄結構和component組件使用心得](https://segmentfault.com/a/11...