图片上传与压缩:Vue 3 与 Element Plus 的实践指南

图片上传与压缩:Vue 3 与 Element Plus 的实践指南

  • 一、前言
    • [1. 需求概述](#1. 需求概述)
    • [2. Vue 3 与 Element Plus 设置](#2. Vue 3 与 Element Plus 设置)
    • [3. 图片上传组件](#3. 图片上传组件)
    • [4. 代码解析](#4. 代码解析)
    • [5. 总结](#5. 总结)

一、前言

在现代 web 开发中,处理用户上传的图片是一项常见任务。为了优化用户体验和减少服务器负担,我们通常需要对图片进行压缩。在这篇文章中,我们将介绍如何在 Vue 3 和 Element Plus 的应用中,实现图片的上传与压缩,并且如何在上传前进行质量验证。

1. 需求概述

在用户上传头像或其他图片时,我们需要:

  1. 确保上传的文件是图片格式。
  2. 对图片进行压缩,以减少上传文件的大小。
  3. 在上传前对压缩后的图片进行质量验证,以确保图片符合要求。

2. Vue 3 与 Element Plus 设置

在本文示例中,我们使用 Vue 3 和 Element Plus 来实现图片上传功能。首先,确保你已经安装了 Vue 3 和 Element Plus。

bash 复制代码
npm install vue@next element-plus

接下来,我们创建一个 el-upload 组件用于图片上传,配合自定义的方法来处理图片压缩和验证。

3. 图片上传组件

我们首先定义一个基本的上传组件。el-upload 组件来自 Element Plus,它提供了强大的文件上传功能。我们将自定义 before-upload 方法来处理图片的压缩和验证。

html 复制代码
<template>
  <el-form-item label="头像" prop="imageId">
    <el-upload
      class="avatar-uploader"
      action="http://xxxxxxxxxxx/fileUpload"
      :show-file-list="false"
      :before-upload="beforeAvatarUpload"
      :data="imageFormData"
      name="files"
      accept="image/*"
    >
      <img v-if="imageUrl" :src="imageUrl" class="avatar" />
      <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
    </el-upload>
  </el-form-item>
</template>

<script setup>
import { ref } from 'vue';
import { ElMessage, ElIcon } from 'element-plus';
import Plus from '@element-plus/icons-vue/Plus';

const imageUrl = ref('');
const imageFormData = ref({});

const beforeAvatarUpload = async (file) => {
  if (!file.type.startsWith("image/")) {
    ElMessage.error("请上传图片!");
    return false;
  }

  const compressedFile = await compressImage(file);

  const isValid = await validateImage(compressedFile);
  if (isValid) {
    // 处理图片预览
    const reader = new FileReader();
    reader.onload = (event) => {
      imageUrl.value = event.target.result;
    };
    reader.readAsDataURL(compressedFile);

    return compressedFile; // 图片合格,继续上传
  } else {
    ElMessage.error("图片质量不合格!");
    return false; // 图片不合格,阻止上传
  }
};

const compressImage = (file) => {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = (event) => {
      const img = new Image();
      img.src = event.target.result;
      img.onload = () => {
        const canvas = document.createElement("canvas");
        const ctx = canvas.getContext("2d");
        canvas.width = 300;
        canvas.height = (img.height / img.width) * 300;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        canvas.toBlob(
          (blob) => {
            resolve(
              new File([blob], file.name, {
                type: "image/jpeg",
                lastModified: Date.now(),
              })
            );
          },
          "image/jpeg",
          0.9
        );
      };
    };
  });
};

const validateImage = async (file) => {
  const formData = new FormData();
  formData.append('file', file);

  try {
    const response = await fetch('http://your-validation-api.com/validate', {
      method: 'POST',
      body: formData,
    });
    const result = await response.json();
    return result.isValid;
  } catch (error) {
    ElMessage.error("图片验证失败!");
    return false;
  }
};
</script>

<style scoped>
.avatar-uploader {
  display: inline-block;
  width: 100px;
  height: 100px;
  border: 1px solid #dcdfe6;
  border-radius: 50%;
  overflow: hidden;
  background: #f5f7fa;
  cursor: pointer;
  text-align: center;
  line-height: 100px;
}
.avatar {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.avatar-uploader-icon {
  font-size: 24px;
  color: #409eff;
}
</style>

4. 代码解析

  • beforeAvatarUpload :此方法在文件上传前被调用。我们使用 compressImage 方法对图片进行压缩,并通过 validateImage 方法验证压缩后的图片质量。

  • compressImage :这个方法使用 FileReaderCanvas 将图片压缩到指定宽度(300px),并保持原始比例。压缩后的图片质量设置为 90%。

  • validateImage :在图片压缩后,我们将其发送到一个图片质量验证 API 接口进行检查。如果图片合格,则返回 true,否则返回 false

  • 样式:通过一些简单的 CSS 样式来美化上传组件和图片预览。

5. 总结

通过以上步骤,我们实现了一个能够在上传前对图片进行压缩和质量验证的功能。这不仅优化了用户体验,也减少了服务器的负担。希望这篇文章对你有所帮助,让你在处理图片上传时更加得心应手。

如果你有任何问题或改进建议,欢迎在评论区留言!

相关推荐
学不会•17 分钟前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS1 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜3 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点3 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow3 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o3 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
刚刚好ā4 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
yqcoder5 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
会发光的猪。6 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客6 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js