美文网首页
前端压缩图片

前端压缩图片

作者: 八妹sss | 来源:发表于2021-06-21 15:41 被阅读0次

原理:
图片文件转换成canvas,例用canvas的quality压缩图片,再将canvas转成文件后上传

    // 压缩图片
    compressImg (file, maxSize, success, error) {
      // 图片小于等于最大图片大小不压缩
      if (file.size <= maxSize * Math.pow(1024, 2)) {
        return success(file)
      }
      const name = file.name // 文件名
      const reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = e => {
        const src = e.target.result

        const img = new Image()
        img.src = src
        img.onload = e => {
          const w = img.width
          const h = img.height
          // 生成canvas
          const canvas = document.createElement('canvas')
          const ctx = canvas.getContext('2d')
          // 创建属性节点
          const anw = document.createAttribute('width')
          anw.nodeValue = w
          const anh = document.createAttribute('height')
          anh.nodeValue = h
          canvas.setAttributeNode(anw)
          canvas.setAttributeNode(anh)

          // 铺底色 PNG转JPEG时透明区域会变黑色
          ctx.fillStyle = '#fff'
          ctx.fillRect(0, 0, w, h)

          ctx.drawImage(img, 0, 0, w, h)
          let quality = 1
          let fileSize = file.size / (1024 * 1024)
          quality = (maxSize / fileSize).toFixed(2)
          // quality值越小,所绘制出的图像越模糊
          const base64 = canvas.toDataURL('image/jpeg', quality) // 图片格式jpeg或webp可以选0-1质量区间

          // 返回base64转blob的值
          console.log(`原图${(src.length / 1024).toFixed(2)}kb`, `新图${(base64.length / 1024).toFixed(2)}kb`)
          // 去掉url的头,并转换为byte
          const bytes = window.atob(base64.split(',')[1])
          // 处理异常,将ascii码小于0的转换为大于0
          const ab = new ArrayBuffer(bytes.length)
          const ia = new Uint8Array(ab)
          for (let i = 0; i < bytes.length; i++) {
            ia[i] = bytes.charCodeAt(i)
          }
          file = new Blob([ab], {type: 'image/jpeg'})
          file.name = name

          success(file)
        }
        img.onerror = e => {
          error(e)
        }
      }
      reader.onerror = e => {
        error(e)
      }
    },
    // 图片上传
    uploadImg (file, success, error) {
      // let size = Math.floor(file.size / 1024)
      // if (size > 1024 * 1) {
      //   this.$message({
      //     message: '建议使用1MB以内的jpg、jpeg、png图片',
      //     type: 'warning'
      //   })
      //   return
      // }
      // 将需要上传的图片压缩成小于等于1M的文件
      this.compressImg(file, 1, file => {
        let appid = sessionStorage.getItem('appid')
        let url = `${this.SERVICE_WECHAT}/upgrade/media/${appid}/upload/newsimg`
        let formData = new FormData()
        formData.append('file', file, file.name)
        this.posts(url, formData).then(rsp => {
          if (rsp.status === 200 || rsp.status === 201) {
            if (success && typeof success === 'function') success(rsp.data.data)
          } else {
            if (error && typeof error === 'function') error(rsp)
          }
        }).catch(e => {
          this.handleError(e)
          if (error && typeof error === 'function') error(e)
        })
      })
    }

原文链接:https://segmentfault.com/a/1190000012037041

相关文章

网友评论

      本文标题:前端压缩图片

      本文链接:https://www.haomeiwen.com/subject/vwmyyltx.html