需求:弄一个文件上传的子组件,我需要上传的文件类型是音乐MP3文件,上传时需要对文件类型、大小、时长做出限制,其中时长限制存在异步问题,后来是通过watch监听间接实现的;

官方文档 el-upload 组件的 before-upload 属性可以做文件格式校检;
官方对该属性的说明是:上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传;

组件代码如下:

<template>
    <el-dialog
        title="上传音乐"
        :visible.sync="isShow"
        @update:visible="val => $emit('update:visible', val)"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        custom-class="video-add-musics-dialog"
        size="tiny">
        <el-tabs v-model="activeName">
            <!-- <el-tab-pane label="本地上传" name="local"> -->
                 <el-upload
                        accept=".mp3"
                        class="upload-demo"
                        drag
                        action="str"  
                        :http-request="handlerChange"
                        :auto-upload="true"
                        :before-upload="beforeAvatarUpload"
                        :before-remove="true"
                        multiple>
                        <i class="el-icon-upload"></i>
                        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
                        <div class="el-upload__tip" slot="tip">仅支持Mp3格式,建议大小在2Mb以内,时长9~60秒。</div>
                    </el-upload> 
                <div class="upload-confirm-bar">
                    <ul class="tips"> 
                        <li>注意:视频自动从音乐片头开始,上传请自行裁剪</li>
                    </ul>
                </div>
        </el-tabs>
        
    </el-dialog>
</template>

我们需要在 beforeAvatarUpload()里对文件格式进行校检
起初 js 代码如下:

beforeAvatarUpload(file) {
                // 限制上传文件大小 2M
                const isLt2M = file.size / 1024 / 1024 < 2;
                const isTime60S = this.audioDuration >= 60 ? true : '';
                // 获取时长
                this.getTimes(file);
                if (!isLt2M) {
                        this.$message.error("上传文件大小不能超过 2MB!");
                        this.fileList = [];
                    } else {
                        if (!isTime60S) {
                            this.$message.error("上传文件时长不能超过60秒!");
                            this.fileList = [];
                        }
                    }
                }
                return isAudio && isLt2M && isTime60S
            },
             getTimes(file) {		//这个和上面是异步,所以上面会拿不到audioDuration 的值
                var content = file;
                //获取录音时长
                var url = URL.createObjectURL(content);
                //经测试,发现audio也可获取视频的时长
                var audioElement = new Audio(url);
                audioElement.addEventListener("loadedmetadata", (_event) => {
                    this.audioDuration = parseInt(audioElement.duration);
                    // console.log(this.audioDuration);
                });
            },

上面这段代码是参考网上的,但实现不了时长限制的效果,原因是两方法异步的,getTimes()将文件时长存进 audioDuration 变量中时 beforeAvatarUpload 已经跑完了;

解决方法,既然是异步,我们需要的是获得时长后然后判断是否作出限制,那么监听 audioDuration(时长) 变量就可以了,等它有值了再判断;

优化后 js 代码如下:

// data里面相关变量
data () {
        return {
            isShow: false,
            activeName: 'local',
            fileList: [],
            musicTitle:" ",
            playTime:0,
            file2:{},
            nick:"" //tb979768_44
        }
    },
    
//文件上传前对文件格式验证
beforeAvatarUpload(file){
            this.file2 = file	// 文件变量要先存起来
            // 限制上传文件大小 1M
            const isLt2M = file.size / 1024 / 1024 < 2;
            if (!isLt2M) {
                    this.$message.error("上传文件大小不能超过 2MB!");
                    this.fileList = [];
                    return false;
                }
            }
          
            this.getTimes(file);
            
        },
        //根据时长判断是否作出限制
        option(file){ 
            if (this.playTime>60) {
                this.$message.error("上传文件时长不能超过60秒!");
                this.fileList = [];
            }   
        },
        //获取文件时长
        getTimes(file) {
                var content = file;
                //获取录音时长
                var url = URL.createObjectURL(content);
                var audioElement = new Audio(url);
                audioElement.addEventListener("loadedmetadata", (_event) => {
                    this.audioDuration = parseInt(audioElement.duration);
                    this.playTime = parseInt(audioElement.duration);
                    // console.log(this.audioDuration);
                });
            },

//上面是在 methods 里面的方法

watch: {
        visible: {
            handler (val) {
                this.isShow = val
            },
            immediate: true
        },		// 监听 playTime 有新值 ,然后在进行判断
        playTime: function(newVal){
              this.option(this.file2)
          },
    }

相关文章:

Vue上传文件案例,文件参数和其他参数同时传递

文件上传参数报错 Required request part ‘file‘ is not present

Logo

前往低代码交流专区

更多推荐