Vue.js中如何为3个不同尺寸要求的平台校验上传图片尺寸与大小
多平台图片上传动态尺寸校验实现方案
基础需求参数
- 平台1:推荐图片尺寸 920×300
- 平台2:推荐图片尺寸 210×200
- 平台3:推荐图片尺寸 790×270
- 全平台统一限制:单张图片大小不超过1MB
- 交互要求:选图后即时预览,尺寸与当前选中平台要求不匹配时显示错误标记
原有实现待修正点
- 尺寸阈值写死为固定宽高,未和当前选中的平台ID做映射关联,无法动态适配不同平台要求
- 大小计算逻辑错误:1MB实际对应1048576字节,原有代码写的100000字节仅约100KB,校验规则里的2048单位也不符合实际
- 逻辑顺序错误:未等尺寸校验通过就直接调用云上传接口,会把不符合要求的图片传到存储服务
- 语法与绑定错误:模板绑定的
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
相关产品推荐
相关产品推荐

