背景
开发上传身份证的功能,图片太大时上传等待时间很久,在前端限制了图片的大小。但是还有一种方法就是前端做一次图片压缩,然后再上传。就可以解决这个问题。先介绍一下如下的几个概念:
FileReader
FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
FileReader.readAsDataURL()
开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的Base64字符串以表示所读取文件的内容。
Canvas toDataURL
toDataURL()是canvas对象的一种方法,用于将canvas对象转换为base64位编码;
总体流程
将选取到的文件,通过Canvas toDataURL()转为base64格式,然后将base64转为blob格式,将blog格式转为File文件,传递给后端。至此完成了图片的压缩。
const convertBase64UrlToBlob = (urlData:any) => {
const arr = urlData.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1]) // atob方法用于解码base64
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], {
type: mime
})
}
const compressImgQuality = (file, quality = 1) => {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => {
const img = new Image()
const canvas = document.createElement('canvas')
const drawer = canvas.getContext('2d')
img.src = reader.result as string
// 图片压缩代码,需要注意的是,img图片渲染是异步的,所以必须在img的onlaod钩子中再进行相应操作
img.onload = function () {
canvas.width = img.width
canvas.height = img.height
drawer.drawImage(img, 0, 0, canvas.width, canvas.height)
const blob = convertBase64UrlToBlob(canvas.toDataURL(file.type, quality))
const resultFiles = new File([blob], file.name, { type: file.type })
resolve(resultFiles)
}
}
})
}