经常遇到用户上传文件的场景,大多数是图像,在满足一些业务时候需要对用户上传的图像进行前端的校验控制,比如体积、长宽、类型等,如果遇到校验不通过的情况分两种一种是阻止上传一种是帮组用户处理出合法的图片。
第一种阻止上传影响用户的体验,用户还要自己找图片处理软件对着规则进行处理。
第二种就需要用到前端的一些技术帮组用户处理图像,目前可以做到压缩体积、压缩宽高、改变图片类型、甚至提供裁切宽进行裁切。

关键知识点:

FileReader
Canvas

关键代码:

1
2
3
4
5
6
7
8
9
10
11
12
// 以base64形式读取文件
reader.readAsDataURL(file)
// 读取成功回调 e.target.result
reader.onload = (e)=>{ img.src = e.target.result }
// canvas画图操作,this指当前image对象,起始点在平面坐标(0,0)处,画一张目标宽高的图像
context.drawImage(file, 0, 0, Width, Height)
// 转为blob对象
canvas.toBlob()
// 转为bae64对象
canvas.toDataURL()
// 图片加载完毕
img.onload = ()=>{}

完整代码

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
type CompressPrams = {
file: object,
mimeType: string,
maxWidth: number,
maxHeight: number,
callback: (blob: object) => any
}
// compress.js
export const compressImage:any = (params: CompressPrams):any => {
const { file, mimeType = 'image/jpeg', callback, maxWidth, maxHeight } = params
if (maxWidth === 0 || maxHeight === 0) {
throw new Error('MaxWidth Or MaxHeight Is Zero')
}
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
const reader = new FileReader()
const img = new Image()

// 以base64形式读取文件
reader.readAsDataURL(file)
// 读取成功回调 e.target.result
reader.onload = (e) => {
img.src = e.target.result
}
// 图片加载完毕
img.onload = function () {
const originWidth = this.width
const originHeight = this.height
let targetWidth = originWidth
let targetHeight = originHeight
// 计算目标宽高,如果不存在就是原始宽高
if (maxWidth && maxHeight) {
if (originWidth / originHeight > maxWidth / maxHeight) { // 原始图片比限定大小比例宽
targetWidth = maxWidth
targetHeight = Math.round(targetWidth * (originHeight / originWidth))
} else { // 原始图片比限定大小比例高或等于
targetHeight = maxHeight
targetWidth = Math.round(targetHeight * (originWidth / originHeight))
}
}
if (maxWidth && !maxHeight) { // 限定宽来比例缩放高
targetWidth = maxWidth
targetHeight = Math.round(targetWidth * (originHeight / originWidth))
}
if (maxHeight && !maxWidth) { // 限定高来比例缩放宽
targetHeight = maxHeight
targetWidth = Math.round(targetHeight * (originWidth / originHeight))
}
canvas.width = targetWidth
canvas.height = targetHeight
// canvas画图操作,this指当前image对象,起始点在平面坐标(0,0)处,画一张目标宽高的图像 注意此时img.onload不是箭头函数
context.drawImage(this, 0, 0, targetWidth, targetHeight)
// 转为blob对象,mimeType为 image/*
canvas.toBlob((blob) => {
// 通过callback回调,传入文件blob对象以及压缩后的目标宽高
callback && callback(blob, {width: targetWidth, height: targetHeight})
}, mimeType)
}
}
1
2
3
4
5
6
7
8
9
10
11
// controller.js
import { compressImage } from 'compress.js'
compressImage({
file: newfile,
mimeType:'image/jpeg',
maxWidth: 1000,
maxHeight: 1000,
callback:(blob)=>{
console.log(blob)
}
})

原创内容,欢迎交流转载请注明出处