最近做一款个人小程序,涉及到图片的上传,发布时没通过,大致意思是说需要做微信内容安全检测,校验一张图片是否含有违法违规内容,看了微信开放文档,
确实一头雾水,也百度搜索了一些大佬的做法,貌似都有报错,搞了老久老久了,实际上总结出来就是传输的格式不对下面我就来说说正确的做法与步骤(我自己项目里面的部分代码,大伙看个思想就行了):
总的来说:因为内容安全接口时不允许直接在前端调用的,有安全问题,所以前端将图片转为base64格式传到后端,后端再由base64转化为buffer,在后端调用内容安全接口就ok了
步骤1.(前端)
从相册中选择一张图片uni.chooseImage---》获取到图片路径tempFilePaths[0] ,重要的看imgSecCheck方法
chooseImage(sourceType) {
const _this = this;
uni.chooseImage({
count: 1, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType,
success: function(chooseRes) {
try {
_this.handleImg(chooseRes.tempFilePaths[0]).then((res) => {
if (res.code !== 200) {
uni.showModal({
content: res.message || '出错了',
showCancel: false
})
}
uni.hideLoading()
})
} catch (e) {
uni.hideLoading()
console.error(e)
}
// finally{
// uni.hideLoading()
// }
}
});
},
async handleImg(localPath) {
const _this = this;
uni.showLoading({
title: '图片处理中...',
mask: true
})
const checkRes = await this.imgSecCheck(localPath)
console.log('checkRes', checkRes)
if (checkRes.code !== 200) {
this.segmentResTempUrl = null
return checkRes
}
}
步骤2.(前端)
先解释一下我为什么要先将图片转化为base64,因为其它办法都已失败告终哈哈
// 校验图片是否含有违法违规内容
async imgSecCheck(localPath) {
const base64Res = await this.getImgBase64(localPath)
if (base64Res.code !== 200) {
return base64Res
}
// c这里的request是对uniCloud.callFunction的一个简单的封装,下面有介绍
return await this.$request({
name: 'file',
dataType: 'json',
data: {
action: 'imgSecCheck',
params: {
source: base64Res.result
}
},
})
},
async getImgBase64(localPath) {
console.log('localPath', localPath)
return new Promise((resolve, reject) => {
uni.getFileSystemManager().readFile({
filePath: localPath,
encoding: 'base64',
success: res => {
let datas = res.data
// console.log('datas', datas)
// const base64 = uni.arrayBufferToBase64(datas)
resolve({
code: 200,
result: datas
})
},
fail: (e) => {
console.error('getImgBase64 fail', e)
reject({
message: 'base64转换出错'
})
}
})
})
},
request.js封装
const request = async(funcParams) => {
const {name,data}=funcParams;
const {action,params}=data;
return new Promise((resolve, reject) => {
uniCloud.callFunction({
name,
data,
success(response) {
console.log(`callFunction(${name}/${action}) response:`, response.result);
switch (response.result.code) {
case 200:
break;
case 10002: // 登录token过期
break;
case 10001: // 用户未授权
break;
default:
break;
}
resolve(response.result);
},
fail(err) {
console.error(`callFunction(${name}/${action}) error:`, err);
reject({message:'请求出错'});
}
})
});
}
export default request
到此前端部分就讲完了,写得有些啰嗦,实际上只需要看imgSecCheck这个方法就行了
步骤3(后端)先看看必要参数
所以还要获取微信access_token
async function getAccessToken() {
let result = null
const res = await uniCloud.httpclient.request(
'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxa954bf263f23a7a6&secret=f025543f4dda4a7809cb42d27b279f35', { // 此处appid和seceret要使用自己真实的
dataType: 'json'
})
if (res.status === 200) {
const {
access_token
} = res.data
result = {
code: 200,
message: '获取getAccessToken成功',
result: access_token
}
} else {
result = {
code: 500,
message: '获取getAccessToken失败',
}
}
return result
}
async function imgSecCheck(params) {
const {
result
} = await getAccessToken()
if (result) {
const {status,data} = await uniCloud.httpclient.request(
`https://api.weixin.qq.com/wxa/img_sec_check?access_token=${result}`, { // 此处appid和seceret要使用自己真实的
dataType: 'json',
files: [Buffer.from(params.source, 'base64')]
})
if(status===200&&data.errcode===0){
return {
code:200,
message:'图片合法'
}
}else{
return {
code:500,
message:'图片出错或违规'
}
}
}
}
exports.main = async (event) => {
let params = event.params || {}
let payload = {}
let res = {}
switch (event.action) {
case 'imgSecCheck':
res = await imgSecCheck(params);
break;
default:
res = {
code: 403,
message: '非法访问'
}
break;
}
//返回数据给客户端
return res
};
至此完结撒花
此功能我整合在了一个自己写的小程序里面,有兴趣的可以微信搜索(toopian)或者扫描小程序码体验一下(就是那个抠图的功能,大家可以体验一下)