1.使用场景
微信小程序/小游戏中凡是使用到图片的地方(包含拍摄、本地相册)理论上都需要做图片内容检查,不能出现敏感人物及不良内容。首先代码提交上传的时候审核人员会做检查,如果没接入内容检查是有概率被打回的,有一些能够避开该检查的方法可以在我另一个文章中看到,但这个避开也只是暂时的,仅应付代码提交时的审核人员。最近有几个小游戏被举报下架了,盲猜是官方有类似脚本会周期性检测图片类应用,所以即使过了审核也会在运行期间被查到(虽然站内信显示的是被人举报,但是我有一个app日访问量都是个位数的也被ban了,谁闲着没事去举报一个冷门应用?)。
2.解决方法
没办法了只能老老实实做后端接口去校验了,这里用的是同步方法img_sec_check(参考资料:https://developers.weixin.qq.com/miniprogram/dev/framework/security.imgSecCheck.html),官方是推荐使用异步方法mediaCheckAsync,但由于异步方法对接相对复杂,不是实时获取结果的,使用限制比较大所以放弃。
但img_sec_check也有限制比如图片大小要在1M以内,图片尺寸不能超过750*1334(实际测试下来发现这个尺寸限制貌似没起到作用,只要不是大的离谱都能正常返回结果)。所以主要限制还是在大小上,这个我们可以使用wx.chooseMedia自带的sizeType: [‘compressed’]来压缩图片大小,所以基本不是问题。
img_sec_check最大的麻烦是在文档上,非常简单,简单到连个demo都么有,php和java勉强还能找到,.net就…更别提.netcore了,全网也很少有相关资料于是干脆写了一篇文章方便大家,以后也方便自己。
3.cocos creator代码
onbtnClick() {
this.lblMessage.node.active = false
console.log(userInfo.isProduction)
let _this = this
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['album', 'camera'],
maxDuration: 30,
sizeType: ['compressed'],
camera: 'back',
success(res) {
//成功以后打开
// 用绝对路径加载设备存储内的资源,比如相册
const absolutePath = res.tempFiles[0].tempFilePath;
try {
//上传图片
wx.uploadFile({
url: 'https://localhost:3400/api/ImgCheck/ImageCheck', //仅为示例,非真实的接口地址
filePath: absolutePath,
name: 'file',
formData: {
'appName': '小程序名字'
},
success(res) {
const checkResult = res.data
if (checkResult == 'false') {
//图片校验不合规,显示错误提示
_this.lblMessage.node.active = true
}
else {
//图片检验通过,做你想做的逻辑吧
assetManager.loadRemote<ImageAsset>(absolutePath, function (err, imageAsset) {
const spriteFrame = new SpriteFrame();
const texture = new Texture2D();
texture.image = imageAsset;
spriteFrame.texture = texture;
})
}
}
})
}
catch (err) {
console.log(err)
}
}
})
}
使用了wx.chooseMedia获取图片,然后调用wx.uploadFile上传到服务器,formData用于传递一些自定义字段,比如我的后端服务是支持多个小程序使用的,那就传递当前小程序的名字,后端进行区分。
4.后端.netcore webapi代码
新建netcore webapi应用,首先注入服务
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
在控制器里增加方法
using ImgCheckWebApi.BE;
using ImgCheckWebApi.Common;
using Microsoft.AspNetCore.Mvc;
namespace ImgCheckWebApi.Controllers
{
[ApiController]
public class ImgCheckController : ControllerBase
{
private IHttpContextAccessor _accessor;
public ImgCheckController(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
[HttpPost]
[Route("api/[controller]/ImageCheck")]
[DisableRequestSizeLimit]
public async Task<ActionResult<bool>> ImageCheck()
{
try
{
//获取图片文件
var file = HttpContext.Request.Form.Files["file"];
//获取cocos中自定义字段appName,表示哪个小程序名使用该接口
var key = HttpContext.Request.Form["appName"][0];
//EF上下文,用于数据库连接
imagecheckContext _context = new imagecheckContext();
//根据app名字获取对应的token,自行实现
var access_token = _context.SystemConfigInfo.FirstOrDefault(x => x.ConfigName == "access_token" && x.ForUserId == key);
if (access_token != null && !string.IsNullOrEmpty(access_token.ConfigValue))
{
HttpHelper http = new HttpHelper();
WxImageSend send = new WxImageSend();
send.access_token = access_token.ConfigValue;
send.media = file;
var result = await http.ImageSecCheck(send);
if (result != null && result.errcode != 0)
return false;
else
return true;
}
else
{
//没有注册过的app返回true,已防用户没法用
return true;
}
}
catch (Exception ex)
{
LogHelper.LogError("ImageCheck异常", ex);
return true;
}
}
}
}
HttpHelper中的ImageSecCheck方法
public async Task<WxImgSecCheck> ImageSecCheck(WxImageSend send)
{
string wxapiImageSecCheckUrl = "https://api.weixin.qq.com/wxa/img_sec_check?access_token=" + send.access_token;
string json = String.Empty;
byte[] bytes = new byte[send.media.Length];
using (var fileStream = send.media.OpenReadStream())
{
fileStream.Read(bytes, 0, (int)send.media.Length);
}
using (var httpClient = new HttpClient())
{
try
{
ByteArrayContent array = new ByteArrayContent(bytes);
array.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
HttpResponseMessage response = await httpClient.PostAsync(wxapiImageSecCheckUrl, array);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
json = responseBody;
}
catch (Exception reqEx)
{
LogHelper.LogError("图片安全校验接口错误", reqEx);
return null;
}
}
var obj = DeserializeJsonToObject<WxImgSecCheck>(json);
return obj;
}
参数的WxImageSend就是一个实体
public class WxImageSend
{
public string access_token { get; set; }
public IFormFile media { get; set; }
}
返回的实体WxImgSecCheck
public class WxImgSecCheck
{
public int errcode { get; set; }
public string errmsg { get; set; }
}
如果之前没有使用过access_token,不知道怎么获取的,可以参考官方文档(https://developers.weixin.qq.com/minigame/dev/api-backend/open-api/access-token/auth.getAccessToken.html)如果在.netcore中使用,可以在webapi中使用Quartz定时更新access_token并保存在数据库,上面"//根据app名字获取对应的token,自行实现"的地方就是从数据库拿取这个access_token的。
Quartz如果有需求的话以后再写个文章介绍吧,功能非常强大可以维护access_token,也可以拿来定时刷新游戏排行榜等等。
搭完这个后端就完成图片内容校验了,妈妈再也不用担心我的小游戏被ban了。另外提醒一点,如果数据格式不对调用了img_sec_check,接口也会返回ok,不能看到ok就认为搞定了,要拿违规的图去做测试,得到高风险结果了才能认为是真的ok了,哪些是违规图,可以百度一些高官的图片,拿这图片去做测试。
以上,有疑问可以留言~
文章讲述了微信小程序在使用图片时需要进行内容检查,以避免敏感信息。开发者分享了如何使用img_sec_check接口进行图片检查,并提供了cocoscreator的代码示例以及后端.netcorewebapi的实现方法,包括图片上传和access_token的处理。同时强调了测试的重要性,确保能识别违规图片。
1959

被折叠的 条评论
为什么被折叠?



