elementUI中el-upload上传时添加同一文件时保证只有一个文件

elementUI中el-upload上传时添加同一文件多次时提示且只显示一个文件并且只上传一个文件怎么处理?
图片描述

阅读 25.6k
5 个回答

这个问题8.1k的阅读,但还没有很合适的答案。现在看到这个问题来回答可能对楼主来说太晚了,但还是认真码一下,希望能对后续看到的人有所帮助。
我知道楼主的意思,因为设置:auto-upload=false,需要一个before-add的钩子来在添加前看文件是否重复,然而element-ui没有提供before-add的钩子。但这个问题看element-ui的源码就可以知道怎么解决,el-upload里面的file是包装过的,如果是要添加的文件,file.status会被设为ready,而上传时会被设为uploading,上传成功会被设为success,上传失败会被设置为fail。而on-change钩子的描述是“文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用”,看到这里包括了“添加文件”,但不包含“删除文件”,所以你可以这么做:绑定on-change函数,在函数内判断传入的file.status是否为ready来判断是不是添加文件,因为从以上描述可知“on-change发现file.status==='ready'”到“on-change是准备添加文件”至少是单射。
下面附上代码:
vue template(用pug来写,省点字数):

div
    label 替换同名文件
    el-switch(v-model="replace")
el-upload(action="" multiple :auto-upload="false"
accept="text/xml, application/xml, application/zip, application/x-zip-compressed"
:on-change="handleChange")

javascript:

export default{
//其他属性,如name
    data(){
        return{
            replace: true,
            msgPromise: Promise.resolve(),
        }
    }
    methods:{
    //其他methods
        handleChange(file, fileList) {
                        //这表示是添加行为
                        console.log(`准备修改文件${file.raw.name}, 此时文件列表长度为${fileList.length}`);
                        if (file.status==='ready') {
                            console.log(`添加了文件${file.raw.name}`);
                            let myFile = file.raw;

                            const type = myFile.type.toLowerCase();
                            const isXML = type === 'text/xml' || type === 'application/xml';
                            const isZip = type === 'application/zip' || type === 'application/x-zip-compressed';
                            if (!(isXML || isZip)) {
                                fileList.pop();
                                this.handleMsg('上传的文件格式不正确', 'error');
                                // 无论是不是增加新文件都更新长度信息
                                return;
                            }

                            const fileIndex = getFileIndex(file, fileList);
                            if (fileIndex >= 0) {
                                if (this.replace) {
                                    fileList[fileIndex] = file;
                                    fileList.pop();
                                    this.handleMsg(`${myFile.name}文件重复,已覆盖该文件`);
                                } else {
                                    fileList.pop();
                                    this.handleMsg(`${myFile.name}文件重复,未覆盖该文件`);
                                }
                            }
        },
        handleMsg(message, type = 'info') {
            const duration = 1500;
            //一定要this.msgPromise = XXX才有用,这样后调用的才会.then接到后面
            //Promise.then().then()和Promise.then(); Promise.then();是不一样的,前者是真串行
            this.msgPromise = this.msgPromise.then(() => {
                this.$message({message, type, duration});
            });
        },
    }
}

其实哪怕没有status,非侵入式判断是否添加的办法也是有的,就是设置一个fileListLength字段,on-change的时候判断传进来的fileList.length是比这个fileListLength大还是一样,长的话肯定是添加,一样的话就是其他操作,做一些处理之后,再把fileListLength字段置为fileList.length(可能有漏洞,因为必须证明这是个单射,主要强调一下办法总比问题多)。
以上代码顺带作为文件类型判断的示例和解决ElMessage层叠的示例,层叠问题参考的Never Yu丶的博客
另判断相同文件可以用MD5,可以用js-spark-md5,大文件就只做首尾chunk检查,也很简单,就不另外写代码了。

楼主同学,可以设置file-list呀,重新清空file-list就达到你的目的了
如:

  :file-list="myFileList"

beforeUpload中 设置 this.myFileList = []

elementUI中el-upload 中有一个钩子函数:before-upload(上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。), 所以你只需要在这个钩子函数中判断即将上传的文件是否在上传列表(或者已上传文件)中,然后在进行处理你希望的逻辑

有问题可以先查看文档,一般来说在文档中都可以找到方法

element :component/upload

changeUpload(file, fileList) {
   this.fileList = fileList.slice(-1)
}
推荐问题
宣传栏