当前位置: 首页 > news >正文

Vue图片压缩方案

在 Vue 项目中处理用户上传的大图片时,通过前端压缩减小图片体积是优化上传体验的有效方式。以下为具体实现方案及相关说明:

一、图片压缩方案对比

不同压缩方案在体积缩减、兼容性、耗时等方面各有特点,具体如下:

方案体积缩减兼容性耗时备注
Canvas 缩放60-85%99%本文主方案
WebP encode额外-30%92%需服务端配合回退 JPG
WebAssembly70-90%92%mozJPEG/avif-js,包大
服务端压缩0%100%前端仍要先传原图

二、核心实现:Canvas 缩放压缩

利用 HTML5 的 Canvas API,通过调整图片尺寸和质量实现压缩,是兼容性和效果平衡较好的方案。

1. 压缩工具函数

核心思路是利用 HTML5 的 Canvas API 对图片进行压缩,主要通过调整图片尺寸和质量来实现。

/*** 图片压缩工具* @param file 原始图片文件* @param options 压缩选项* @returns 压缩后的图片文件*/
export const compressImage = async (file: File,options: {maxWidth?: number;    // 最大宽度maxHeight?: number;   // 最大高度quality?: number;     // 图片质量 0-1} = {}
): Promise<File | null> => {// 默认配置const {maxWidth = 1200,maxHeight = 1200,quality = 0.8} = options;return new Promise((resolve) => {// 创建图片对象const img = new Image();const objectUrl = URL.createObjectURL(file);img.src = objectUrl;img.onload = () => {URL.revokeObjectURL(objectUrl);// 计算压缩后的尺寸(保持比例)let width = img.width;let height = img.height;// 如果图片尺寸超过最大限制,按比例缩小if (width > maxWidth || height > maxHeight) {const ratio = Math.min(maxWidth / width, maxHeight / height);width = width * ratio;height = height * ratio;}// 创建Canvas元素const canvas = document.createElement('canvas');canvas.width = width;canvas.height = height;// 绘制图片到Canvasconst ctx = canvas.getContext('2d');if (!ctx) {resolve(null);return;}ctx.drawImage(img, 0, 0, width, height);// 将Canvas内容转换为Blobcanvas.toBlob((blob) => {if (!blob) {resolve(null);return;}// 转换为File对象const compressedFile = new File([blob],file.name,{ type: blob.type, lastModified: Date.now() });resolve(compressedFile);},file.type || 'image/jpeg',quality);};img.onerror = () => {URL.revokeObjectURL(objectUrl);resolve(null);};});
};
2. Vue3 组件中使用示例
<template><div class="image-upload"><inputtype="file"accept="image/*"@change="handleFileChange"class="file-input"/><div v-if="previewUrl" class="preview"><img :src="previewUrl" alt="预览图" class="preview-img" /><p>原始大小: {{ originalSize }}KB</p><p v-if="compressedSize">压缩后大小: {{ compressedSize }}KB</p></div></div>
</template><script setup lang="ts">
import { ref } from 'vue';
import { compressImage } from '@/utils/imageCompressor';const previewUrl = ref('');
const originalSize = ref(0);
const compressedSize = ref(0);const handleFileChange = async (e: Event) => {const input = e.target as HTMLInputElement;if (!input.files || input.files.length === 0) return;const file = input.files[0];// 显示原始文件大小originalSize.value = Math.round(file.size / 1024);// 如果文件小于500KB,不压缩直接使用if (file.size < 500 * 1024) {previewUrl.value = URL.createObjectURL(file);compressedSize.value = originalSize.value;return;}// 压缩图片const compressedFile = await compressImage(file, {maxWidth: 1000,maxHeight: 1000,quality: 0.7});if (compressedFile) {previewUrl.value = URL.createObjectURL(compressedFile);compressedSize.value = Math.round(compressedFile.size / 1024);// 这里可以将compressedFile上传到服务器// await uploadToServer(compressedFile);}
};
</script><style scoped>
.image-upload {display: flex;flex-direction: column;gap: 1rem;
}.file-input {padding: 0.5rem;border: 1px solid #ccc;border-radius: 4px;
}.preview {margin-top: 1rem;
}.preview-img {max-width: 100%;border-radius: 4px;box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
</style>

三、服务端二次校验(Node 示例)

router.post('/upload', multer().single('file'), async (req, res) => {const { buffer, mimetype, size } = req.file;if (size > 1024 * 1024) return res.status(413).send('too big');if (!['image/jpeg', 'image/webp'].includes(mimetype)) return res.status(400).send('bad type');// 计算 SSIM 或 Magic Number 防止“伪造压缩”const metadata = await sharp(buffer).metadata();if (metadata.width! > 1600) return res.status(400).send('width overflow');// 真正落盘await putToOSS(buffer, mimetype);res.json({ url });
});

四、注意事项

  1. 压缩会损失一定画质,需根据业务场景平衡画质与文件大小;
  2. 对于几十 MB 的超大图片,可考虑分阶段压缩(先大幅缩小尺寸,再调整质量);
  3. 服务端必须进行二次校验,防止前端绕过压缩逻辑上传超大文件。
http://www.dtcms.com/a/513077.html

相关文章:

  • python去掉不是ts文件的链接
  • 性病医院网站优化服务商中国品牌网站设计
  • win2008网站404成都职业培训网络学院
  • 网站源码授权wordpress调用相关页面
  • Excel 宏安全设置与强制启用宏
  • 万柳网站建设html网站开发中的应用
  • 中国站长小程序源码能直接用吗
  • 《通信之道—从微积分到5G》阅读笔记
  • 郑州网站建设网页设计网站备案转入
  • 广州网站建设出售sae wordpress 主题
  • 为什么在大数据处理场景下,存储过程比编程语言更合适?
  • 电子商务网站建设与管理课件辽宁建设工程信息网备案
  • 【软件安装】在 Visual Studio 2022 中安装 RDLC 报表插件的详细教程
  • Cloud Studio 免环境搭建创建机器学习环境并运行 Pytorch 案例
  • 11、【Ubuntu】【VSCode】VSCode 断联问题分析:getent 命令(一)
  • 网站被降权会发生什么影响吗怀化汽车网站
  • 护照阅读器识别行驶证:汽车检测站的效率助力
  • 网站一般字体网上做设计网站
  • Cortex-M中的DWT(Data Watchpoint and Trace,数据观察点与跟踪单元)
  • 自助建网站系统看电影pexels免费素材网站
  • 做评选活动的网站网站建设费会计处理
  • 私人程序定制:综合能源混合博弈
  • 蓝色网站源码室内展厅设计公司
  • 西电信息化建设网站山东网站制作设计
  • Django 的动态特性:从 Python 动态机制到框架设计思想
  • 矽塔 SA8204 输入耐压36V 2.5A可调过流保护 集成故障报告的智能过压/过流保护芯片
  • 十堰微网站建设网络交友的网站建设
  • Spring—注解开发
  • Hugging Face 2025年10月21日 Top 10 热门AI模型
  • 事件网站推广杭州平面设计公司