图片上传压缩

12/30/2022 技巧

# 图片压缩

<template>
  <div>
    <input id="fileInput" type="file" />
    <img id="img" src="" alt="" />
  </div>
</template>

<script setup>
import { onMounted } from 'vue'

const initUpload = () => {
  let fileId = document.getElementById('fileInput')
  let img = document.getElementById('img')
  fileId.onchange = function (e) {
    let file = e.target.files[0]
    console.log('file', file)
    compressImg(file, 0.92, 'png').then((res) => {
      //compressImg方法见附录
      console.log(res)
      img.src = window.URL.createObjectURL(res.file)
    })
  }
}

/**
 * 压缩图片方法
 * @param {file} file 文件
 * @param {Number} quality 图片质量(取值0-1之间默认0.92)
 */
const compressImg = (file, quality, imgType) => {
  var qualitys = 0.52
  const type = imgType ? 'image/' + imgType : file.type // 图片类型
  console.log(parseInt((file.size / 1024).toFixed(2)))
  if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
    qualitys = 0.85
  }
  if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
    qualitys = 0.92
  }
  if (quality) {
    qualitys = quality
  }
  if (file[0]) {
    return Promise.all(Array.from(file).map((e) => compressImg(e, qualitys))) // 如果是 file 数组返回 Promise 数组
  } else {
    return new Promise((resolve) => {
      console.log(file)
      if ((file.size / 1024).toFixed(2) < 300) {
        resolve({
          file: file,
        })
      } else {
        const reader = new FileReader() // 创建 FileReader
        reader.onload = ({ target: { result: src } }) => {
          const image = new Image() // 创建 img 元素
          image.onload = async () => {
            const canvas = document.createElement('canvas') // 创建 canvas 元素
            const context = canvas.getContext('2d')
            var targetWidth = image.width
            var targetHeight = image.height
            var originWidth = image.width
            var originHeight = image.height
            if (
              1 * 1024 <= parseInt((file.size / 1024).toFixed(2)) &&
              parseInt((file.size / 1024).toFixed(2)) <= 10 * 1024
            ) {
              var maxWidth = 1600
              var maxHeight = 1600
              targetWidth = originWidth
              targetHeight = originHeight
              // 图片尺寸超过的限制
              if (originWidth > maxWidth || originHeight > maxHeight) {
                if (originWidth / originHeight > maxWidth / maxHeight) {
                  // 更宽,按照宽度限定尺寸
                  targetWidth = maxWidth
                  targetHeight = Math.round(maxWidth * (originHeight / originWidth))
                } else {
                  targetHeight = maxHeight
                  targetWidth = Math.round(maxHeight * (originWidth / originHeight))
                }
              }
            }
            if (
              10 * 1024 <= parseInt((file.size / 1024).toFixed(2)) &&
              parseInt((file.size / 1024).toFixed(2)) <= 20 * 1024
            ) {
              maxWidth = 1400
              maxHeight = 1400
              targetWidth = originWidth
              targetHeight = originHeight
              // 图片尺寸超过的限制
              if (originWidth > maxWidth || originHeight > maxHeight) {
                if (originWidth / originHeight > maxWidth / maxHeight) {
                  // 更宽,按照宽度限定尺寸
                  targetWidth = maxWidth
                  targetHeight = Math.round(maxWidth * (originHeight / originWidth))
                } else {
                  targetHeight = maxHeight
                  targetWidth = Math.round(maxHeight * (originWidth / originHeight))
                }
              }
            }
            canvas.width = targetWidth
            canvas.height = targetHeight
            context.clearRect(0, 0, targetWidth, targetHeight)
            context.drawImage(image, 0, 0, targetWidth, targetHeight) // 绘制 canvas
            const canvasURL = canvas.toDataURL(type, qualitys)
            const buffer = atob(canvasURL.split(',')[1])
            let length = buffer.length
            const bufferArray = new Uint8Array(new ArrayBuffer(length))
            while (length--) {
              bufferArray[length] = buffer.charCodeAt(length)
            }
            const miniFile = new File([bufferArray], file.name, {
              type: type,
            })
            console.log({
              file: miniFile,
              origin: file,
              beforeSrc: src,
              afterSrc: canvasURL,
              beforeKB: Number((file.size / 1024).toFixed(2)),
              afterKB: Number((miniFile.size / 1024).toFixed(2)),
              qualitys: qualitys,
            })
            resolve({
              file: miniFile,
              origin: file,
              beforeSrc: src,
              afterSrc: canvasURL,
              beforeKB: Number((file.size / 1024).toFixed(2)),
              afterKB: Number((miniFile.size / 1024).toFixed(2)),
            })
          }
          image.src = src
        }
        reader.readAsDataURL(file)
      }
    })
  }
}

onMounted(() => {
  initUpload()
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
Last Updated: 12/30/2022, 2:33:12 PM