小程序canvas實現圖片壓縮

原本用小程序寫了一個本地化的圖片應用,不存在服務端的交互行爲

結果提交審覈的時候仍是被打回了

好的!立刻整改

應用的交互大概就是這樣css

咱們須要在選擇圖片後

對圖片作一次安全校驗
html

啓用雲開發

如今咱們須要一個 後端接口 來實現圖片的 安全校驗 功能
node

這時候臨時搭個Node服務好像不太現實

又不是什麼正經項目

因而就想到了微信的雲開發功能

用起來真實方便快捷
git

至於圖片的校驗方法

直接用雲函數調用 security.imgSecCheck 接口就行了github

流程

chooseImage() {
  /// 用戶選擇圖片
  wx.chooseImage({
    count: 1,
    sizeType: ['original', 'compressed'],
    sourceType: ['album', 'camera'],
    success: async res => {
      if (res.errMsg === 'chooseImage:ok') {
        wx.showLoading({ title: '圖片加載中' })
        // 獲取圖片臨時地址
        const path = res.tempFilePaths[0]
        // 將圖片地址實例化爲圖片
        const image = await loadImage(path, this.canvas)
        // 壓縮圖片
        const filePath = await compress.call(this, image, 'canvas_compress')
        // 校驗圖片合法性
        const imgValid = await checkImage(filePath)
        wx.hideLoading()
        if (!imgValid) return
        // 圖片安全檢測經過,執行後續操做
        ...
    }
  })
}

圖片壓縮

因爲 security.imgSecCheck 對圖片有尺寸限制canvas

因此在圖片上傳前要先對超出尺寸的圖片進行壓縮處理
基本邏輯就是

超出尺寸的圖片等比例縮小就行了

咱們先要有一個canvas元素

用來處理須要壓縮的圖片小程序

<template>
  <view class="menu-background">
    <view class="item replace" bindtap="chooseImage">
      <i class="iconfont icon-image"></i>
      <text class="title">圖片</text>
      <text class="sub-title">圖片僅供本地使用</text>
    </view>
    //
    // canvas
    //
    <canvas
      type="2d"
      id="canvas_compress"
      class="canvas-compress"
      style="width: {{canvasCompress.width}}px; height: {{canvasCompress.height}}px"
    />
  </view>
</template>

將canvas移到視野不可見到位置後端

.canvas-compress
    position absolute
    left 0
    top 1000px

圖片進行壓縮處理api

/**
 * 壓縮圖片
 * 將尺寸超過規範的圖片最小限度壓縮
 * @param {Image} image 須要壓縮的圖片實例
 * @param {String} canvasId 用來處理壓縮圖片的canvas對應的canvasId
 * @param {Object} config 壓縮的圖片規範 -> { maxWidth 最大寬度, maxHeight 最小寬度 }
 * @return {Promise} promise返回 壓縮後的 圖片路徑
 */
export default function (image, canvasId, config = { maxWidth: 750, maxHeight: 1334 }) {
  // 引用的組件傳入的this做用域
  const _this = this
  return new Promise((resolve, reject) => {
    // 獲取圖片原始寬高
    let width = image.width
    let height = image.height
    // 寬度 > 最大限寬 -> 重置尺寸
    if (width > config.maxWidth) {
      const ratio = width / config.maxWidth
      width = config.maxWidth
      height = height / ratio
    }
    // 高度 > 最大限高度 -> 重置尺寸
    if (height > config.maxHeight) {
      const ratio = height / config.maxHeight
      height = config.maxHeight
      width = width / ratio
    }
    // 設置canvas的css寬高
    _this.canvasCompress.width = width
    _this.canvasCompress.height = height
    const query = this.createSelectorQuery()
    query
      .select(`#${canvasId}`)
      .fields({ node: true, size: true })
      .exec(async res => {
        // 獲取 canvas 實例
        const canvas = res[0].node
        // 獲取 canvas 繪圖上下文
        const ctx = canvas.getContext('2d')
        // 根據設備dpr處理尺寸
        const dpr = wx.getSystemInfoSync().pixelRatio
        canvas.width = width * dpr
        canvas.height = height * dpr
        ctx.scale(dpr, dpr)
        // 將圖片繪製到 canvas
        ctx.drawImage(image, 0, 0, width, height)
        // 將canvas圖片上傳到微信臨時文件
        wx.canvasToTempFilePath({
          canvas,
          x: 0,
          y: 0,
          destWidth: width,
          destHeight: height,
          complete (res) {
            if (res.errMsg === 'canvasToTempFilePath:ok') {
              // 返回臨時文件路徑
              resolve(res.tempFilePath)
            }
          },
          fail(err) {
            reject(err)
          }
        })
      })
  })
}

圖片安全校驗

雲函數 checkImage.js
const cloud = require('wx-server-sdk')
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})
/**
 * 校驗圖片合法性
 * @param {*} event.fileID 微信雲存儲的圖片ID
 * @return {Number} 0:校驗失敗;1:校驗經過
 */
exports.main = async (event, context) => {
  const contentType = 'image/png'
  const fileID = event.fileID
  try {
    // 根據fileID下載圖片
    const file = await cloud.downloadFile({
      fileID
    })
    const value = file.fileContent
    // 調用 imgSecCheck 藉口,校驗不經過接口會拋錯
    // 必要參數 media { contentType, value }
    const result = await cloud.openapi.security.imgSecCheck({
      media: {
        contentType,
        value
      }
    })
    return 1
  } catch (err) {
    return 0
  }
}
組件調用雲函數封裝
/**
 * 校驗圖片是否存在敏感信息
 * @param { String } filePath
 * @return { Promise } promise返回校驗結果
 */
export default function (filePath) {
  return new Promise((resolve, reject) => {
    // 先將圖片上傳到雲開發存儲
    wx.cloud.uploadFile({
      cloudPath: `${new Date().getTime()}.png`,
      filePath,
      success (res) {
        // 調用雲函數-checkImage
        wx.cloud.callFunction({
          name: 'checkImage',
          data: {
            fileID: res.fileID
          },
          success (res) {
            // res.result -> 0:存在敏感信息;1:校驗經過
            resolve(res.result)
            if (!res.result) {
              wx.showToast({
                title: '圖片可能含有敏感信息, 請從新選擇',
                icon: 'none'
              })
            }
          },
          fail (err) {
            reject(err)
          }
        })
      },
      fail (err) {
        reject(err)
      }
    })
  })
}
本文demo

本文代碼倉庫

https://github.com/luosijie/f...promise

謝謝閱讀!!!

相關文章
相關標籤/搜索