方法:直接复制
javascript
// 核心压缩方法(纯函数,无this)
// ✅ 优化后的【可用】压缩方法(替换你原有代码里的同名方法)
const imageCompress = async (file, quality = 0.7, maxWidth = 1920) => {
return new Promise((resolve, reject) => {
if (!file || !file.type.startsWith('image/')) {
reject(new Error('非图片文件,无需压缩'));
return;
}
const img = new Image()
img.setAttribute('crossOrigin', 'anonymous')
const originalUrl = URL.createObjectURL(file)
img.src = originalUrl
// 图片加载失败容错
img.onerror = () => {
URL.revokeObjectURL(originalUrl);
reject(new Error('图片加载失败,无法压缩'));
};
img.onload = () => {
let { width, height } = img
// 等比例缩放,避免变形
if (width > maxWidth) {
const scale = maxWidth / width
width = maxWidth
height = height * scale
}
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = width
canvas.height = height
ctx.clearRect(0, 0, width, height)
ctx.drawImage(img, 0, 0, width, height)
canvas.toBlob(
(blob) => {
if (!blob) {
reject(new Error('图片压缩失败'));
return;
}
// 生成压缩后的File文件,保留原文件名/格式
const compressFile = new File([blob], file.name, { type: file.type })
const compressUrl = URL.createObjectURL(blob)
resolve({
originalUrl,
compressUrl,
originalSize: file.size,
compressSize: blob.size,
compressFile // ✅ 核心:压缩后的文件对象,用于后续上传
})
},
file.type,
quality // 0.7是9M图片的黄金值:体积压至800KB左右,画质无明显损失
)
URL.revokeObjectURL(originalUrl)
}
})
}
调用:图片上传的beforeUpload方法中使用
javascript
const beforeUpload = async (file) => {
// 1. 原有格式校验:保留不变
const isImage = ['image/jpeg', 'image/png'].includes(file.type)
const isLt10M = file.size / 1024 / 1024 <= 10
if (!isImage) {
ElMessage.error('只能上传JPG/PNG格式图片!')
return false // 校验失败,终止上传
}
if (!isLt10M) {
ElMessage.error('图片大小不能超过10M!')
return false // 校验失败,终止上传
}
// 2. 校验通过 → 执行图片压缩(核心新增逻辑)
try {
console.log(`开始压缩【${file.name}】,原大小:${(file.size/1024/1024).toFixed(2)}MB`)
const compressRes = await imageCompress(file, 0.7, 1920)
console.log(`压缩完成,新大小:${(compressRes.compressSize/1024/1024).toFixed(2)}MB`)
ElMessage.success(`图片压缩成功,体积减小${Math.round((1 - compressRes.compressSize/file.size)*100)}%`)
// ✅ 返回压缩后的文件 → el-upload会自动用这个文件继续上传流程
return compressRes.compressFile
} catch (err) {
ElMessage.error(`图片压缩失败:${err.message},将上传原图`)
return file // 压缩失败兜底,上传原图
}
}
实测:8M左右压缩到300k-500k左右,具体大小可以自己按压缩比例调整