有用没用的图片压缩方案

159 阅读2分钟

一. 技术方案概述

在Vue3+Vite项目中实现图片前端压缩,主要涉及以下技术方案:

  1. 使用HTML5 Canvas API进行图片压缩
  2. 结合FileReader实现本地图片读取
  3. 通过Blob对象处理压缩后的图片数据
  4. 支持自定义压缩质量参数
  5. 兼容主流浏览器环境

二. 核心实现代码

2.1 图片压缩工具函数

/**  * 图片压缩函数  *
 *  @param {File} file - 原始图片文件  
 * * @param {number} [quality=0.7] - 压缩质量(0-1之间)  
* * @returns {Promise<Blob>} - 压缩后的图片Blob对象  */
  const compressImage = async (file, quality = 0.7) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = async (e) => {
      try {
        const img = new Image()
        img.onload = () => {
          const canvas = document.createElement('canvas')
          const ctx = canvas.getContext('2d')                      // 保持原始图片比例          
          const originalWidth = img.width
          const originalHeight = img.height
          let newWidth = originalWidth
          let newHeight = originalHeight
          if (newWidth > 2000) {
            // 最大宽度限制            
            newWidth = 2000
            newHeight = (newWidth / originalWidth) * originalHeight
          }
          canvas.width = newWidth
          canvas.height = newHeight
          // 绘制压缩后的图片           
          ctx.drawImage(img, 0, 0, newWidth, newHeight)
          // 获取压缩后的数据          
          const blob = canvas.toBlob((blob) => { resolve(blob) }, 'image/jpeg', quality)
        }
        img.onerror = reject
      } catch (error) { reject(error) }
    }
    reader.readAsDataURL(file)
  })
}

2.2 Vue组件集成方案

<template>  
  <div>    
    <input type="file" accept="image/*" @change="handleFileUpload">     
    <button @click="uploadCompressed">上传压缩图片</button>     
    <div v-if="previewImage">       
      <img :src="previewImage" alt="预览" style="max-width: 100%">     
    </div>   
  </div> 
</template>  
<script>
import { ref } from 'vue'
export default {
  setup() {
    const previewImage = ref(null)
    const file = ref(null)
    const handleFileUpload = (e) => {
      file.value = e.target.files[0]
      if (file.value) {
        const reader = new FileReader()
        reader.onload = () => { previewImage.value = reader.result }
        reader.readAsDataURL(file.value)
      }
    }
    const uploadCompressed = async () => {
      if (!file.value) return
      try { const compressedBlob = await compressImage(file.value, 0.7)
        // 这里可以调用上传接口
        // const formData = new FormData()
        // formData.append('image', compressedBlob)
        // await axios.post('/api/upload', formData)        
        console.log('压缩完成:', compressedBlob)
      } catch (error) { console.error('压缩失败:', error) }
    }
    return { previewImage, handleFileUpload, uploadCompressed }
  }
}
</script> 

三. 技术实现细节

1、 压缩算法原理

  • Canvas API压缩:通过canvas的toBlob方法,将图片绘制到canvas上并转换为Blob对象
  • 质量参数控制:quality参数控制JPEG压缩质量(0-1),数值越小压缩率越高
  • 尺寸自适应:根据原始尺寸自动调整,保持宽高比例

四. 完整项目集成方案

4.1 Vite配置优化

在vite.config.js中添加图片类型支持:

export default {  
// ... 
build: {    
rollupOptions: {       
output: {         
assetFileNames: 'assets/[name].[ext]'      
}   }   }} 

4.2 错误处理方案

const compressImage = async (file, quality = 0.7) => {   
return new Promise((resolve, reject) => {    
// ...原有代码...         
img.onerror = () => {       reject(new Error('图片加载失败'))     }          
try {      
// ...原有代码...     
} catch (error) {   
reject(error)     }   }) } 

五. 兼容性处理

  • 添加Polyfill支持旧浏览器
  • 自动检测浏览器兼容性
  • 提供降级方案(直接上传原图)