IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 小程序图片安全审核方案与security.imgSecCheck不能校验超过1M图片的解决思路 -> 正文阅读

[移动开发]小程序图片安全审核方案与security.imgSecCheck不能校验超过1M图片的解决思路

背景:

微信截图_20211014152023.png
如上图,我的小程序涉及图片功能上线还没两天就被人搞了(上传了黄图然后被举报)。通过查看得知UGC平台类小程序,涉及到平台内用户发布,平台都要对用户发布内容设置违法违规内容过滤机制。当天连夜修改于是有了这篇文章。

本文用到的图片内容安全检测为小程序自带的同步API:security.imgSecCheck

优点:免费(白嫖的),小程序自带,无须额外申请,格式支持PNG、JPEG、JPG、GIF,单个 appId 调用上限为 2000 次/分钟,200,000 次/天,基本满足需要。

缺点:图片大小限制1M ,图片尺寸不超过 750px x 1334px,还有就是这个API不太稳定的样子,超时的概率挺多,社区他们技术专员给的答案是服务高峰时有少量超时导致

虽然文档写的是图片尺寸不超过 750px x 1334px,但是实际用的时候大过了也基本不报错。

代码实现:

小程序端:
timer = null
state = {
    quality: 0.3,
    cWidth: 0,
    cHeight: 0,
}
//上传图片
chooseImage = () => {
        const _ = this;
        const { quality } = this.state
        Taro.chooseImage({
            count: 1,
            sizeType: ['original', 'compressed'],
            sourceType: ['album'],
            success(result) {
                const tempFilePath = result.tempFilePaths[0];
                let size = result.tempFiles[0].size;
                if (size > 1024 * 1024 * 8) {//大于8M返回
                    return Taro.showToast({
                        title: '图片大于8M啦',
                        icon: 'none'
                    })
                }
               if (size < 1024 * 800) { //小于800kb压缩
                    const status = await _.imgSecCheck(tempFilePath)
                    if (status == true) {
                        console.log('通过了处理');
                        //走检测通过处理
                    }
                } else {
                    Taro.getImageInfo({
                        src: tempFilePath,
                        success: function (res) {
                            _.setState({//设置原始宽高
                                cWidth: res.width,
                                cHeight: res.height
                            }, async () => {
                                try {
                                    const imagePath = await _.getCanvasImg(tempFilePath, res.width, res.height, quality);
                                    const status = await _.imgSecCheck(imagePath)
                                    if (status == true) {
                                        console.log('通过了处理');
                                        //走检测通过处理
                                    }

                                } catch (error) {
                                }
                            })
                        }
                    })
                }
            }
        })
    }
 
    //压缩图片
    getCanvasImg(path, w, h, q) {
        return new Promise((resolve, reject) => {
            var _ = this;
            const ctx = Taro.createCanvasContext('myCanvas');
            ctx.clearRect(0, 0, w, h);
            ctx.drawImage(path, 0, 0, w, h);
            ctx.draw(false, function () {
                _.timer = setTimeout(() => {
                    Taro.canvasToTempFilePath({
                        canvasId: 'myCanvas',
                        fileType: 'jpg',
                        quality: q,
                        destWidth: w,
                        destHeight: h,
                        success: function success(res) {
                            _.setState({
                                imagePath:res.tempFilePath
                            })
                            clearTimeout(_.timer)
                            resolve(res.tempFilePath)
                        },
                        fail: function (e) {
                            clearTimeout(_.timer)
                            Taro.showModal({
                                title: '提示',
                                content: JSON.stringify(e),
                            })
                            reject(e)
                        }
                    });
                }, 500)
            });
        })
    }
    //检测图片
   async imgSecCheck(src) {
    try {
        //上传到云存储
        const uploadResult = await Taro.cloud.uploadFile({
        //云储存的路径及文件名
            cloudPath: new Date().getTime() + "-" + Math.floor(Math.random() * 1000),
            filePath: src,
        })
        //图片检测
        const json = await Taro.cloud.callFunction({
            name: "service",
            data: {
                action: "checkImg",
                fileID: uploadResult.fileID
            }
        })
        if (json.result.errCode == 0) { //图片没问题
            return true;
        }
        else if (json.result.errCode == 87014) {
            return Taro.showToast({
                title: '图片含有违法违规内容',
                duration: 2000,
                icon: 'none'
            });
        }
        else {
            return Taro.showToast({
                title: '请重新上传',
                duration: 2000,
                icon: 'none'
            });
        }
    } catch (error) {
        return Taro.showToast({
            title: error,
            duration: 2000,
            icon: 'none'
        });
    }
}
 render() {
        const { cWidth, cHeight} = this.state
        const _style = {
            width: cWidth + 'px',
            height: cHeight + 'px',
            position: 'fixed',
            top: '-9999px',
            left: '-9999px'
        }
      
        return (
            <View>
                <Button onClick={this.chooseImage}>上传</Button>
                <Canvas canvas-id='myCanvas' className='myCanvas' style={_style}></Canvas>
            </View>
        )
    }
云函数端:
module.exports = async (event, context) => {
    try {
        const fileID = event.fileID
        const res = await cloud.downloadFile({
            fileID: fileID,
        })
       //这里也可以把fileID和用户关联起来add在记录里,方便观察。
       
        const buffer = res.fileContent
        return await cloud.openapi.security.imgSecCheck({
            media: {
                contentType: "image/png",
                value: buffer
            }
        })

    } catch (err) {

        return err
    }
}

测了几波下来基本不报错,检测也正常。

啥,你问我为啥不用微信的wx.compressImage压缩图片接口api,因为它会反向压缩,压缩了还更大,社区里也有狠多反馈的问题。
以下是quality设置为0.3时几次压缩大小测试,可以看到压缩还可以。图片大时可以动态检测原始图片大小设置quality值。

最后欢迎关注

欢迎关注小程序“进阶的大前端”,用云开发写的,1000多道前端面试题在线查看。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-16 19:45:19  更:2021-10-16 19:47:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:39:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码