You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js中如何为3个不同尺寸要求的平台校验上传图片尺寸与大小

多平台图片上传动态尺寸校验实现方案

基础需求参数

  • 平台1:推荐图片尺寸 920×300
  • 平台2:推荐图片尺寸 210×200
  • 平台3:推荐图片尺寸 790×270
  • 全平台统一限制:单张图片大小不超过1MB
  • 交互要求:选图后即时预览,尺寸与当前选中平台要求不匹配时显示错误标记

原有实现待修正点

  1. 尺寸阈值写死为固定宽高,未和当前选中的平台ID做映射关联,无法动态适配不同平台要求
  2. 大小计算逻辑错误:1MB实际对应1048576字节,原有代码写的100000字节仅约100KB,校验规则里的2048单位也不符合实际
  3. 逻辑顺序错误:未等尺寸校验通过就直接调用云上传接口,会把不符合要求的图片传到存储服务
  4. 语法与绑定错误:模板绑定的selectFile方法和代码里的selectedFile命名不统一,文件输入框未加对应ref,存在多余闭合div标签,选择文件按钮的reset类型会意外清空表单

改造后完整实现

1. 数据层配置

data() {
  return {
    isLoading: false,
    loadingImage: false,
    imageError: '',
    // 平台尺寸映射表,key替换为你实际的平台ID值即可
    platformSizeConfig: {
      1: { width: 920, height: 300 },
      2: { width: 210, height: 200 },
      3: { width: 790, height: 270 }
    },
    MAX_FILE_SIZE: 1 * 1024 * 1024, // 1MB对应字节数
    formData: {
      PlatformTypeID: '',
      TypeofDocument: '',
      LinkToDocument: ''
    },
    rules: [
      (images) => {
        if (!images || !images.length) return '请选择上传图片'
        const hasOversize = images.some(img => img.size > 1024*1024)
        return hasOversize ? '图片大小不能超过1MB' : true
      }
    ]
  }
}

2. 选图、校验、上传逻辑

methods: {
  // 触发文件选择框
  selectFile() {
    this.$refs.fileInput.click()
  },
  // 文件选择变更处理
  async onFileChange(e) {
    this.imageError = ''
    this.loadingImage = true
    const files = e.target.files || e.dataTransfer.files
    if (!files || !files[0]) {
      this.loadingImage = false
      return
    }
    const file = files[0]
    // 校验文件类型
    if (file.type.indexOf('image/') !== 0) {
      this.imageError = '请选择jpg/jpeg/png格式的图片'
      this.loadingImage = false
      return
    }
    // 校验文件大小
    if (file.size > this.MAX_FILE_SIZE) {
      this.imageError = `图片大小为${(file.size/1024/1024).toFixed(2)}MB,不能超过1MB`
      this.loadingImage = false
      return
    }
    // 获取当前选中平台的尺寸要求
    const currentPlatformSize = this.platformSizeConfig[this.formData.PlatformTypeID]
    if (!currentPlatformSize) {
      this.imageError = '请先选择要上传的平台'
      this.loadingImage = false
      return
    }
    // 读取图片做尺寸校验
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = async (evt) => {
      const img = new Image()
      img.src = evt.target.result
      img.onload = async () => {
        // 尺寸校验,若不需要严格匹配只需不超过尺寸,把!==改成>即可
        if (img.width !== currentPlatformSize.width || img.height !== currentPlatformSize.height) {
          this.imageError = `当前平台要求图片尺寸为${currentPlatformSize.width}×${currentPlatformSize.height},您上传的图片尺寸为${img.width}×${img.height}`
          this.loadingImage = false
          return
        }
        // 所有校验通过后再执行上传
        this.formData.TypeofDocument = file.name.split('.').pop().toLowerCase()
        await CMS.uploadImageToCloud(file, (fileUrl) => {
          this.formData.LinkToDocument = fileUrl
          this.loadingImage = false
        })
      }
      img.onerror = () => {
        this.imageError = '图片解析失败,请重新选择'
        this.loadingImage = false
      }
    }
    reader.onerror = () => {
      this.imageError = '文件读取失败,请重试'
      this.loadingImage = false
    }
  },
  async submit() {
    // 提交前兜底校验
    if (this.imageError || !this.formData.LinkToDocument) return
    this.isLoading = true
    // 原有业务提交逻辑
    // ...
    this.isLoading = false
  }
}

3. 模板部分修正

<form @submit.prevent="submit" style="padding: 10px;">
  <div class="form-group">
    <label>{{ $t('Platforms') }}</label>
    <select class="form-control" v-model="formData.PlatformTypeID">
      <option
        v-for="(platform, index) in platformTypes"
        :key="index"
        :value="platform.ID"
      >{{ platform.Name }}</option>
    </select>
  </div>
  <div class="form-group">
    <label>{{ $t('Select Image') }}</label>
    <div class="row">
      <div class="col-md-4 mb-5">
        <!-- 校验不通过时给预览图加红框做错误标记 -->
        <img
          v-if="formData.LinkToDocument"
          :src="formData.LinkToDocument"
          class="img-responsive"
          height="100"
          :style="imageError ? 'border: 2px solid red;' : ''"
        />
        <img
          src="~/static/img/loading.gif"
          height="100"
          v-if="!formData.LinkToDocument && loadingImage"
        />
        <!-- 错误提示文本 -->
        <div v-if="imageError" style="color: red; margin-top: 8px;">{{ imageError }}</div>
      </div>
    </div>
    <input
      type="file"
      ref="fileInput"
      accept="image/jpg, image/jpeg,image/png"
      v-on:change="onFileChange"
      id="fileInput"
      style="display: none"
    />
    <button
      type="button"
      class="btn btn-primary"
      align="center"
      :disabled="loadingImage"
      @click="selectFile"
    >
      {{ $t('Choose File') }}
    </button>
  </div>
  <div class="row marginTop">
    <div class="col-6 col-md-6">
      <button
        v-if="!isLoading"
        type="submit"
        id="saveBtn"
        class="btn btn-success text_white btn-block text-white btn-md btn-responsive"
        tabindex="7"
        :disabled="!!imageError"
      >
        {{ $t('Save') }}
      </button>
      <button
        v-if="isLoading"
        class="btn disabled btn-success text_white btn-block text-white btn-md btn-responsive"
        tabindex="7"
      >
        <i class="fa fa-spin fa-spinner fa-1x"></i>
      </button>
    </div>
    <div class="col-6 col-md-6">
      <router-link
        to=""
        class="btn btn-default btn-block btn-md btn-responsive"
      >{{ $t('Cancel') }}</router-link>
    </div>
  </div>
</form>

补充优化建议

  • 可以给平台下拉选择加watch监听,切换平台时如果已经上传了图片,自动重新校验尺寸是否符合新平台要求
  • 如果业务允许尺寸存在小幅误差,可以把尺寸判断的严格相等逻辑改成范围判断,比如允许宽高误差在10像素内
  • 错误提示可以根据业务需要改成toast提示,或者在预览图旁边加错误图标,交互更明显

内容的提问来源于stack exchange,提问作者David chukwuma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 23:27:32