原理:
图片文件转换成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)
})
})
}
网友评论