SOURCE

// base64转file
    base64ToFile(urlData, fileName) {
      const arr = urlData.split(',')
      const mime = arr[0].match(/:(.*?);/)[1]
      const bytes = atob(arr[1]) // 解码base64
      let n = bytes.length
      const ia = new Uint8Array(n)
      while (n--) {
        ia[n] = bytes.charCodeAt(n)
      }
      return new File([ia], fileName, { type: mime })
    },
    // base64转canvas
    async imgToCanvas(base64) {
      const img = document.createElement('img')
      img.setAttribute('src', base64)
      await new Promise((resolve) => (img.onload = resolve))
      const canvas = document.createElement('canvas')
      canvas.width = img.width
      canvas.height = img.height
      // 坐标(0,0) 表示从此处开始绘制,相当于偏移。
      canvas.getContext('2d').drawImage(img, 0, 0)
      return canvas
    },
    // canvas转img
    convasToImg(canvas, type) {
      const image = new Image()
      image.src = canvas.toDataURL(type, 0.6)
      return image
    },
    // 添加水印
    addWatermark(canvas, text) {
      const ctx = canvas.getContext('2d')

      const fontSize = 20
      const fontColor = 'rgba(0, 0, 0, 0.2)'
      const angle = -30
      const tileWidth = 280
      const tileHeight = 280

      for (let i = 0; i < canvas.width; i += tileWidth) {
        for (let j = 0; j < canvas.height; j += tileHeight) {
          ctx.save()

          ctx.font = fontSize + 'px Arial'
          ctx.fillStyle = fontColor

          ctx.translate(i, j + tileHeight / 2 + fontSize / 2)
          ctx.rotate(angle * Math.PI / 180)

          ctx.fillText(text, 0, 0)
          ctx.restore()
        }
      }
      return canvas
    },
    // 文件转base64
    fileByBase64(file, callback) {
      const reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = function(e) {
        callback(e.target.result)
      }
    },
    // 自定义上传
    beforeUpload(file) {
      return new Promise((resolve, reject) => {
        this.fileByBase64(file, async(base64) => {
          const tempCanvas = await this.imgToCanvas(base64)
          const canvas = this.addWatermark(tempCanvas, '仅适用于短信实名认证使用')
          const img = this.convasToImg(canvas, file.type)

          const newFile = this.base64ToFile(img.src, file.name)
          resolve(newFile)
        })
      })
    },
    async handleUpload(param) {
      const file = await this.beforeUpload(param.file)
      const uploadProgressEvent = progressEvent => {
        this.uploading = true
        this.loadProgress = Math.floor((progressEvent.loaded * 100) / progressEvent.total)
        if (this.loadProgress >= 99) {
          this.loadProgress = 99
        }
      }
      upFilesFD({ file }, uploadProgressEvent).then(res => {
        if (res.code == 200) {
          console.log(res, 'upload')
          this.loadProgress = 100
          this.uploaded = true
          this.imageUrl = res.data.url
          this.$emit('on-success', res.data.path)
          setTimeout(() => {
            this.uploading = false
          }, 1000)
        } else {
          this.msgError('上传失败')
          this.uploaded = false
          this.uploading = false
        }
      })
    }
console 命令行工具 X clear

                    
>
console