vue中使用图片压缩

422 阅读2分钟

柯南和小兰背靠背 夕阳 日落 4K动漫壁纸 3840x2160_彼岸图网.jpg

介绍

在vue中使用第三方插件 image-conversion 封装的图片压缩方法

代码说明

npm install image-conversion

const imageConversion = require("image-conversion")
/**
 * 压缩图片文件
 * @param {File} file 原始图片文件
 * @param {Object} config 压缩配置项(可选)
 * @param {Number} config.size     目标大小(单位:KB)
 * @param {Number} config.accuracy 压缩精度,范围 0-1(默认 0.9)
 * @param {Number} config.scale    缩放比例,范围 0-10(可选,优先使用 width/height)
 * @param {Number} config.width    结果图像的宽度(会自动根据图片大小生成)
 * @param {Number} config.height   结果图像的高度(会自动根据图片大小生成)
 * @param {Number} config.accuracy  图片质量 0-1,默认 0.92(质量越低压缩越强)
 * @returns {Promise<File>} 返回压缩后的图片文件
 */
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
  console.log('config', config);

  const resAvatarBlob = await imageConversion.compressAccurately(file, config)
  const resAvatarFile = new window.File(
    [resAvatarBlob],
    file.name,
    { type: file.type },
  )
  console.log('压缩后的大小', resAvatarFile.size / 1024)
  return resAvatarFile
}
/**
 * 计算图片在最大宽高限制下的目标尺寸
 * @param {File} file 图片文件
 * @param {Object} config 配置项
 * @param {Number} config.maxWidth  最大宽度,默认 1400
 * @param {Number} config.maxHeight 最大高度,默认 1400
 * @returns {Promise<{ targetWidth: number, targetHeight: number }>}
 */
// 获取压缩后的图片尺寸
function getTargetFileSize (file, config = { maxWidth: 1400, maxHeight: 1400 }) {
  return new Promise(resolve => {
    const { maxWidth, maxHeight } = config
    let reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      let img = new Image();
      img.src = reader.result;
      img.onload = () => {
        let targetWidth = img.width
        let targetHeight = img.height
        let originWidth = img.width
        let 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 })
      }
    }
  })
}

使用案例

<template>
  <el-upload
    class="upload-demo"
    action="" <!-- 实际开发中配置上传地址 -->
    :http-request="handleUpload"
    :show-file-list="false"
    accept="image/*"
  >
    <el-button type="primary">上传图片</el-button>
  </el-upload>
</template>

<script setup>
import { compressConversion } from '@/utils/compressConversion' // 路径按实际修改
import { ElMessage } from 'element-plus'

const handleUpload = async ({ file }) => {
  try {
    const compressedFile = await compressConversion(file, { accuracy: 0.9, size: 300 })

    // 示例上传请求
    const formData = new FormData()
    formData.append('file', compressedFile)

    // 替换为你的上传接口
    const res = await fetch('/api/upload', {
      method: 'POST',
      body: formData
    })

    if (!res.ok) throw new Error('上传失败')
    ElMessage.success('上传成功')
  } catch (err) {
    console.error(err)
    ElMessage.error('上传失败')
  }
}
</script>