本文档核心是总结如何在 Vue 项目中,通过 image-conversion
第三方插件实现图片压缩,包含依赖安装、核心工具函数封装、组件内使用案例及关键注意事项,解决大图片上传慢、占用存储空间大的问题。
一、依赖安装
首先需安装 image-conversion
插件,该插件提供精准的图片压缩能力,支持按尺寸、质量、目标大小等多维度配置:
npm install image-conversion
二、核心工具函数封装
封装两个核心函数(通常放在 utils/compressConversion.js
),分别负责“计算压缩后目标尺寸”和“执行图片压缩”,兼顾灵活性与复用性。
1. 压缩主函数:compressConversion
作用:接收原始图片文件和配置项,返回压缩后的 File 对象,核心是调用 image-conversion
的 compressAccurately
方法实现精准压缩。
参数 | 类型 | 说明 |
---|---|---|
file |
File |
待压缩的原始图片文件(从上传组件中获取) |
config |
Object |
压缩配置项(可选,有默认值) |
config.size |
Number |
目标文件大小(单位:KB),默认 300KB |
config.accuracy |
Number |
图片质量(0-1,值越低压缩越强),默认 0.9;注意文档中存在重复定义,实际以“图片质量”语义为准 |
config.scale |
Number |
缩放比例(0-10),优先级低于 width/height,可选 |
config.width |
Number |
压缩后图片宽度(自动按原图比例计算,优先于 scale) |
config.height |
Number |
压缩后图片高度(自动按原图比例计算,优先于 scale) |
函数逻辑:
- 打印压缩前文件大小(单位:KB),便于调试;
- 调用
getTargetFileSize
计算压缩后的目标宽高,避免图片尺寸超限; - 将目标宽高传入配置项,调用
image-conversion.compressAccurately
生成压缩后的 Blob; - 将 Blob 转为 File 对象(保留原文件名和类型),打印压缩后大小,返回该 File 对象。
代码示例:
const imageConversion = require("image-conversion");
export async function compressConversion(file, config = { accuracy: 0.9, size: 300 }) {
// 打印压缩前大小(调试用)
console.log("压缩前的大小", file.size / 1024);
// 计算压缩后目标宽高(避免尺寸超限)
const { targetWidth, targetHeight } = await getTargetFileSize(file);
config.width = targetWidth;
config.height = targetHeight;
// 执行压缩,生成 Blob
const resAvatarBlob = await imageConversion.compressAccurately(file, config);
// Blob 转 File 对象(保留原文件名和类型)
const resAvatarFile = new window.File(
[resAvatarBlob],
file.name,
{ type: file.type }
);
// 打印压缩后大小(调试用)
console.log("压缩后的大小", resAvatarFile.size / 1024);
return resAvatarFile; // 返回压缩后的 File 对象(Promise 包裹)
}
2. 尺寸计算函数:getTargetFileSize
作用:辅助函数,根据原图尺寸和最大宽高限制,计算压缩后的目标宽高(等比例缩放,避免拉伸变形),防止图片尺寸过大(默认限制最大宽高 1400px)。
参数 | 类型 | 说明 |
---|---|---|
file |
File |
原始图片文件 |
config |
Object |
尺寸配置项(可选) |
config.maxWidth |
Number |
允许的最大宽度,默认 1400px |
config.maxHeight |
Number |
允许的最大高度,默认 1400px |
函数逻辑:
- 用
FileReader
将图片转为 DataURL,再通过Image
对象获取原图宽高; - 若原图宽高未超过
maxWidth/maxHeight
,直接返回原图尺寸; - 若超限,按“宽高比”等比例缩放:
- 原图更宽(宽高比 > 最大宽高比):按
maxWidth
限定宽度,计算对应高度; - 原图更高(宽高比 ≤ 最大宽高比):按
maxHeight
限定高度,计算对应宽度。
- 原图更宽(宽高比 > 最大宽高比):按
代码示例:
function getTargetFileSize(file, config = { maxWidth: 1400, maxHeight: 1400 }) {
return new Promise(resolve => {
const { maxWidth, maxHeight } = config;
const reader = new FileReader();
// 读取图片为 DataURL
reader.readAsDataURL(file);
reader.onload = () => {
const img = new Image();
img.src = reader.result;
// 图片加载完成后,计算目标尺寸
img.onload = () => {
let targetWidth = img.width;
let targetHeight = img.height;
const originWidth = img.width;
const originHeight = img.height;
// 尺寸超限,等比例缩放
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));
}
}
resolve({ targetWidth, targetHeight });
};
};
});
}
三、组件中使用案例(基于 Element Plus)
以 Element Plus 的 el-upload
组件为例,通过 http-request
自定义上传逻辑,在上传前先执行图片压缩,再提交压缩后的文件。
1. 模板部分
通过 el-upload
提供上传入口,限制仅接收图片类型,隐藏默认文件列表:
<template>
<el-upload
class="upload-demo"
action="" <!-- 无需配置,因用 http-request 自定义上传 -->
:http-request="handleUpload" <!-- 自定义上传逻辑 -->
:show-file-list="false" <!-- 隐藏默认文件列表 -->
accept="image/*" <!-- 仅允许上传图片 -->
>
<el-button type="primary">上传图片</el-button>
</el-upload>
</template>
2. 脚本部分(Script Setup 语法)
引入压缩函数和消息提示组件,在 handleUpload
中完成“压缩 → 构建 FormData → 接口提交 → 结果提示”流程:
<script setup>
// 引入压缩函数(路径按实际项目调整)
import { compressConversion } from '@/utils/compressConversion';
// 引入 Element Plus 消息提示
import { ElMessage } from 'element-plus';
// 自定义上传逻辑
const handleUpload = async ({ file }) => {
try {
// 1. 执行图片压缩(可自定义配置,此处用默认值)
const compressedFile = await compressConversion(file, {
accuracy: 0.9, // 图片质量
size: 300 // 目标大小 300KB
});
// 2. 构建 FormData(符合接口提交格式)
const formData = new FormData();
formData.append('file', compressedFile); // 传入压缩后的文件
// 3. 调用上传接口(替换为项目实际接口地址)
const res = await fetch('/api/upload', {
method: 'POST',
body: formData
});
// 4. 处理结果
if (!res.ok) throw new Error('上传失败');
ElMessage.success('上传成功');
} catch (err) {
// 错误处理
console.error('图片上传/压缩失败:', err);
ElMessage.error('上传失败');
}
};
</script>
四、关键注意事项
- 配置项优先级:
width/height
(目标宽高)优先级高于scale
(缩放比例),建议优先用宽高控制尺寸,避免拉伸。 - 默认配置说明:
- 最大宽高:默认 1400px(超过则等比例缩放);
- 图片质量:默认 0.9(兼顾清晰度和压缩率);
- 目标大小:默认 300KB(可根据接口限制调整)。
- 异步处理:压缩函数返回
Promise<File>
,必须用async/await
或.then()
处理,避免直接使用未压缩的文件。 - 兼容性:
image-conversion
支持主流现代浏览器,若需兼容 IE,需额外处理FileReader
和Promise
兼容性。 - 接口适配:提交时需用
FormData
格式(符合大多数文件上传接口要求),接口地址和参数名需按项目实际调整。
最后,为了方便你在项目中快速复用,要不要我帮你整理一份可直接复制的工具函数文件,包含完整注释和默认配置,你只需替换接口地址即可使用?