事情经过是这样的,这段时间在开发一个二维码美化小程序,昨天中午修复了一个bug后提交给微信审核,晚上收到审核结果后惊呆了,居然没有通过,毕竟自己只是增加了一个setTimeout方法,看到驳回原因后觉得还是挺有意思的:
看完之后理解了,小程序审核人员在小程序里面上传了张18禁图片,然后告诉我,你这样不行啊,怎么能不进行图片鉴黄呢,万一带坏了小盆友该怎么办。那为什么之前的审核你都给通过了?第一次做图片工具类的小程序,还真是没想到审核会有这波操作。行吧行吧,看在你是腾讯的份上(其实是鉴黄接口不收费,虽然云函数超过免费额度后会收费,但是价格还能接受),你要加就给你加呗。
1、准备工作
security.imgSecCheck文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.imgSecCheck.html
看了一下security.imgSecCheck文档,发现调用图片内容安全识别接口有两种方式,第一种是通过HTTPS 调用,第二种是云调用。虽然第一种可以通过直接请求接口调用,但是需要使用access_token,个人感觉还是比较麻烦的,所以选择了云调用。
使用云调用第一步就是需要开通云开发功能,具体开通流程这里就不进行描述了,选择免费的就行(顺带吐槽一下云开发开始割韭菜啦,具体可以参考别人写的文章:小程序云开发新版套餐解读)。
2. 配置云开发
由于这个小程序之前在创建的时候没有勾选云开发,所以需要自己配置一下。
首先是在根目录下的project.config.json
中设置云函数目录:
"cloudfunctionRoot": "cloud/"
然后在根目录下创建cloud
文件夹,创建完成后,这个文件夹右下角会带有一个云图标:
3、创建云函数
在微信开发者工具中右击刚才创建的文件夹,点击新建Node.js云函数,创建一个新的云函数,我这边创建的云函数名称是imgSecCheck,然后在这个云函数目录下的config.json
中配置api权限:
{
"permissions": {
"openapi": [
"security.imgSecCheck"
]
}
}
4、编写云函数
由于这个小程序中的图片是在本地进行编辑和保存,不需要上传到服务器,所以直接将图片直接传给接口就行了,在imgSecCheck目录下的index.js
文件中编写云函数:
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({
env: 'your env'
})
// 云函数入口函数
exports.main = async (event, context) => {
try {
const res = await cloud.openapi.security.imgSecCheck({
media: {
contentType: 'image/png',
value: Buffer.from(event.value)
}
})
return res
} catch (error) {
return error
}
}
其中env
的值可以在开发者工具-云开发-设置-环境ID中拿到,然后将这个云函数进行上传:
5、小程序端调用
上传完成后即可在小程序端调用,下方为从相册选取图片后进行图片内容安全识别的一个demo:
wx.chooseImage({
count: 1, // 默认9
sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album'], // 可以指定来源是相册还是相机,默认二者都有
success(res) {
const src = res.tempFilePaths[0]
wx.getFileSystemManager().readFile({
filePath: src,
success: buffer => {
wx.showLoading({
title: '图片合规性检查中',
mask: true
})
wx.cloud.callFunction({
name: 'imgSecCheck', // 之前创建的云函数名称
data: {
value: buffer.data // 传入的值
}
}).then(res => {
wx.hideLoading()
if (res.result.errCode === 87014) {
wx.showToast({
title: '图片违规,请重新上传其他图片',
icon: 'none'
})
} else if (res.result.errCode === 0) {
// 图片内容正常 TODO
} else {
wx.showToast({
title: '检测出错,错误码为:' + res.result.errCode,
icon: 'none'
})
}
}).catch(error => {
wx.hideLoading()
console.log(error)
wx.showToast({
title: `检测出错,请重试`,
icon: 'none'
})
})
}
})
}
})
6、遇到问题
编写完小程序端代码后,使用起来很顺利,看官方描述图片大小限制为1m,然后用PS生成了一张5M左右的图片上传识别,本来准备看一下超过大小限制后的报错信息,没想到云函数正确返回了数据,完美,提交代码。
提交后使用真机测试体验版,发现怎么上传都没有用,然后使用真机调试看了一下报错信息:
看了一会云开发错误码后没有得到有效的信息,以为是图片大小超过了1M,便多尝试了几张图片,发现结果都是一样的,直到上传了一张几乎为纯白色的图片接口才返回数据。计算了一下这些图片的大小,发现只有几十k大小的图片才有几率能被接口识别,超过100k大小的图片都是报错。文档中说好的图片大小限制为1m呢?
7、更换实现方法
在经历了一系列百度搜索后,自己依旧没有找到问题的解决办法(有知道问题所在原因的小伙伴还希望在评论区指导一下),便决定更换一种实现方法,先将图片上传到云端,然后然云函数在云端下载上传后的图片进行识别。
8、开通存储功能
在微信开发者工具-云开发-存储中开通云存储功能,然后新建一个temp文件夹:
9、修改小程序端代码
先将图片上传,获取到文件id后传给云函数:
wx.chooseImage({
count: 1, // 默认9
sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album'], // 可以指定来源是相册还是相机,默认二者都有
success(res) {
const src = res.tempFilePaths[0]
wx.showLoading({
title: '上传中',
mask: true
})
wx.cloud.uploadFile({
// 指定上传到的云路径
cloudPath: 'temp/' + new Date().getTime() + "-" + Math.floor(Math.random() * 1000),
// 指定要上传的文件的小程序临时文件路径
filePath: src,
// 成功回调
success: res => {
wx.hideLoading()
const fileID = res.fileID
wx.showLoading({
title: '图片合规性检查中',
mask: true
})
wx.cloud.callFunction({
name: 'imgSecCheck', // 之前创建的云函数名称
data: {
value: fileID // 传入的值
}
}).then(res => {
wx.hideLoading()
if (res.result.errCode === 87014) {
wx.showToast({
title: '图片违规,请重新上传其他图片',
icon: 'none'
})
} else if (res.result.errCode === 0) {
// 图片内容正常 TODO
} else {
wx.showToast({
title: '检测出错,错误码为:' + res.result.errCode,
icon: 'none'
})
}
}).catch(error => {
wx.hideLoading()
console.log(error)
wx.showToast({
title: `检测出错,请重试`,
icon: 'none'
})
})
},
fail: error => {
wx.hideLoading()
console.log(error)
wx.showToast({
title: '图片上传出错,请重试',
icon: 'none'
})
}
})
}
})
10、修改云函数
云函数首先拿到文件id下载文件,然后再进行图片内容识别。由于我这边图片用完后不需要保存,所以在识别完成后将图片删除,以免占用过多的免费存储空间:
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({
env: 'your env'
})
// 云函数入口函数
exports.main = async (event, context) => {
const file = await cloud.downloadFile({
fileID: event.value
})
try {
const res = await cloud.openapi.security.imgSecCheck({
media: {
contentType: 'image/png',
value: file.fileContent
}
})
cloud.deleteFile({
fileList: [event.value]
})
return res
} catch (error) {
return error
}
}
11、体验
最终效果可以扫描下方小程序码,然后在自定义二维码-自定义背景图-生成图片中体验。
8 条评论
你的文章充满了欢乐,让人忍不住一笑。http://www.cqfadianji.com
你的文章充满了欢乐,让人忍不住一笑。http://www.lzfdzy.com
不错不错,我喜欢看
博主真是太厉害了!!!
小程序中的云函数对data的大小限制导致,具体可以参考文档:
1. 说明:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/functions/Cloud.callFunction.html
2. 解法:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/utils/Cloud.CDN.html
可以依此简化下客户端部分的代码(不用手动设定cdn)
在文档中看到大小限制了,确实是这个原因导致的,感谢大佬