0
点赞
收藏
分享

微信扫一扫

Vue 图片压缩核心方案总结:基于 image-conversion 插件的实现

本文档核心是总结如何在 Vue 项目中,通过 image-conversion 第三方插件实现图片压缩,包含依赖安装、核心工具函数封装、组件内使用案例及关键注意事项,解决大图片上传慢、占用存储空间大的问题。

一、依赖安装

首先需安装 image-conversion 插件,该插件提供精准的图片压缩能力,支持按尺寸、质量、目标大小等多维度配置:

npm install image-conversion

二、核心工具函数封装

封装两个核心函数(通常放在 utils/compressConversion.js),分别负责“计算压缩后目标尺寸”和“执行图片压缩”,兼顾灵活性与复用性。

1. 压缩主函数:compressConversion

作用:接收原始图片文件和配置项,返回压缩后的 File 对象,核心是调用 image-conversioncompressAccurately 方法实现精准压缩。

参数 类型 说明
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)

函数逻辑

  1. 打印压缩前文件大小(单位:KB),便于调试;
  2. 调用 getTargetFileSize 计算压缩后的目标宽高,避免图片尺寸超限;
  3. 将目标宽高传入配置项,调用 image-conversion.compressAccurately 生成压缩后的 Blob;
  4. 将 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

函数逻辑

  1. FileReader 将图片转为 DataURL,再通过 Image 对象获取原图宽高;
  2. 若原图宽高未超过 maxWidth/maxHeight,直接返回原图尺寸;
  3. 若超限,按“宽高比”等比例缩放:
    • 原图更宽(宽高比 > 最大宽高比):按 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>

四、关键注意事项

  1. 配置项优先级width/height(目标宽高)优先级高于 scale(缩放比例),建议优先用宽高控制尺寸,避免拉伸。
  2. 默认配置说明
    • 最大宽高:默认 1400px(超过则等比例缩放);
    • 图片质量:默认 0.9(兼顾清晰度和压缩率);
    • 目标大小:默认 300KB(可根据接口限制调整)。
  3. 异步处理:压缩函数返回 Promise<File>,必须用 async/await.then() 处理,避免直接使用未压缩的文件。
  4. 兼容性image-conversion 支持主流现代浏览器,若需兼容 IE,需额外处理 FileReaderPromise 兼容性。
  5. 接口适配:提交时需用 FormData 格式(符合大多数文件上传接口要求),接口地址和参数名需按项目实际调整。

最后,为了方便你在项目中快速复用,要不要我帮你整理一份可直接复制的工具函数文件,包含完整注释和默认配置,你只需替换接口地址即可使用?

举报

相关推荐

0 条评论