el-upload选择多个文件同时上传带参,on-change校验文件列表数据删除文件

本文详细介绍了一个基于Element UI的表单设计,包括任务选择、文件上传功能的实现。通过v-model、v-for等指令实现了数据绑定和动态选项,同时使用了自定义上传方法handleUpload进行文件处理,并通过FormData对象组织上传数据。最后,Java后端接收并处理上传的文件。

样式:


form表单代码

<el-form>
<el-form-item>
  <el-row>
    <el-col :span="24">
      <el-form-item label="采集任务" prop="taskId">
        <el-select v-model="form.taskId" filterable placeholder="请选择">
          <el-option
            v-for="item in taskOptions"
            :key="item.id"
            :label="item.taskName"
            :value="item.id">
          </el-option>
        </el-select>
      </el-form-item>
    </el-col>
  </el-row>
</el-form-item>
<el-form-item>
  <el-upload
    ref="upload"
    action="/as"
    multiple
    :http-request="handleUpload"
    :on-change="handleChangeFile"
    :auto-upload="false"
    :limit="5">
    <el-button size="small" type="primary">选择文件</el-button>
    <div slot="tip" class="el-upload__tip">一次只能上传5个文件</div>
  </el-upload>
</el-form-item>
<el-form-item>
  <el-row>
    <el-col :span="24" align="center">
      <el-button type="primary" @click="handlePush"  style="margin-top: 20px">点击上传    
  </el-button>
    </el-col>
  </el-row>
</el-form-item>
</el-form>

 


data添加参数:

//任务列表
taskOptions : [],
form: {
  taskId: undefined,
},
//上传文件数组
files:[],

method方法: 

handleUpload(raw){
  this.files.push(raw.file);
},
async handlePush(){
    this.$refs.upload.submit() // 这里是执行文件上传的函数,其实也就是获取我们要上传的文件
    let fd = new FormData();
    fd.append('taskId',this.taskId)
    this.files.forEach(function (file) {
      fd.append('filename', file, file.name); // 因为要上传多个文件,所以需要遍历一下才行
    })
    
    //请求后台方法
    addCollectionDataList(fd).then(res=>{
      //请求后台成功返回处理
    })
  },
// 选择上传文件校验,
handleChangeFile(file, fileList, name) {
  let index = fileList.findIndex( fileItem => {
    return fileItem.uid === file.uid
  });
//上传文件后缀
  let extension = file.name.split(".")[1];
  if(true){  //判断条件根据自己业务    
    fileList.splice(index, 1); // 从上传文件列表删除当前选中文件
    return false;  
  }
},

java后台代码

@PostMapping("/fileUpload")
public Result fileUpload(@RequestParam("filename") MultipartFile[] files, @RequestParam("taskId")Integer taskId, HttpServletRequest request){
  //文件储存目录
  String realPath = "" ; 
  File path = new File(realPath); 
  if(!path.exists()){
   path.mkdirs(); 
  } 
  //判断file数组不能为空并且长度大于0 
  if(files != null && files.length > 0){ 
    //循环获取file数组中得文件 
    for(int i = 0;i < files.length;i++){ 
    MultipartFile file = files[i]; 
    //保存文件
    if (!file.isEmpty()){
       ..........  //执行文件保存
    }
  }
}
<think>我们面对的需求是:在Vue3中使用Element Plus的el-upload组件,通过on-change事件校验上传文件类型,不符合条件的文件不显示在文件列表中,同时支持多选。 分析: 1. el-upload组件在multiple开启时支持多选。 2. on-change事件在文件状态改变时触发(添加文件上传成功、上传失败等)。 3. 我们可以在on-change事件中检查文件的类型,如果不符合要求,则从文件列表中移除该文件。 实现思路: - 使用el-upload组件,设置`multiple`为true(支持多选)。 - 绑定`on-change`事件(在Element Plus中,使用`@change`绑定事件)。 -change事件处理函数中,判断文件类型,如果不符合,则从el-upload组件的文件列表中移除该文件。 注意:Element Plus的el-upload组件内部维护了一个文件列表(fileList),我们需要操作这个文件列表。 在Vue3中,我们可以使用ref来引用el-upload组件,然后通过组件的ref来操作其内部的fileList。但是,更推荐的做法是使用受控的文件列表,即通过`:file-list`绑定一个我们自己的响应式变量(比如uploadFileList),然后通过修改这个变量来控制文件列表。 步骤: 1. 在模板中,el-upload组件绑定`file-list`属性到一个响应式数组(如uploadFileList),并设置`auto-upload`为false(如果不需要自动上传)。 2. 设置`multiple`属性为true。 3. 绑定`@change`事件处理函数(如handleChange)。 4. 在handleChange函数中,我们能够接收到三个参数:file(当前改变的文件)、fileList(当前的文件列表,注意这个可能是内部临时列表,我们不应该直接修改它)、以及可能的事件对象。但是,由于我们使用了自己控制的file-list(uploadFileList),所以实际上我们操作的是uploadFileList。 5. 注意:change事件触发时,新文件会被临时加入,我们需要在事件中判断,如果文件类型不符合,就不将其加入到我们控制的uploadFileList中。但是,由于el-upload组件内部也会维护一个列表,所以我们需要通过自己控制的file-list来覆盖。 具体做法: - 在data中(Vue3的setup中)定义一个ref数组:const uploadFileList = ref([]); - 在handleChange函数中,我们只将符合类型的文件添加到uploadFileList中。 但是注意:change事件会被多次触发(每个文件状态变化都会触发),而且当用户选择多个文件时,change事件会触发多次(每个文件一次)。所以我们需要在每次触发时判断当前文件是否合法,合法则加入,不合法则忽略。 然而,我们需要注意的是,el-upload组件在文件选择后会自动将文件添加到其内部文件列表中,然后触发change事件。如果我们使用自己控制的uploadFileList,那么组件就会显示我们提供的uploadFileList。因此,我们可以在change事件中这样处理: -文件符合条件时,我们将该文件加入到uploadFileList中(注意:这里我们只添加符合条件的文件)。 - 不符合条件的文件,我们不加入uploadFileList,这样它就不会显示。 但是,这样会有一个问题:我们如何获取到新加入的文件?因为change事件中的file参数就是当前变化的文件。我们可以根据这个file进行判断。 另外,我们还需要注意:当删除文件时,change事件也会触发,所以我们需要处理删除的情况。但是,删除操作通常是由用户点击文件列表中的删除按钮触发的,此时文件已经被移除了,我们不需要做额外的类型判断。因此,我们主要处理的是新增文件的情况。 在change事件中,file对象有一个status属性,当文件被加入时,status是'ready'(准备状态)。所以我们只处理状态为'ready'的文件。 实现: 1. 在handleChange函数中,判断file.status是否为'ready',如果是,则进行文件类型校验。 2. 如果文件类型符合要求,则将该file对象添加到uploadFileList中(注意:这里我们使用数组的追加方式,但要注意避免重复,因为每个文件触发一次)。 3. 如果不符合,则忽略,这样uploadFileList中就不会有该文件,因此也不会显示。 但是,这样会导致一个问题:我们如何避免重复添加?因为同一个文件可能因为其他状态变化再次触发change事件(比如上传进度等)。因此,我们只在状态为'ready'时添加一次。 另一种做法:我们不在change事件中向uploadFileList添加文件,而是根据每次change事件触发后,从事件参数中拿到当前所有文件列表(fileList),然后过滤掉不符合条件的,再赋值给uploadFileList。但是这样可能会频繁触发整个列表的重新渲染,性能稍差。 考虑到多选时,用户一次选择多个文件,会触发多次change事件(每个文件一次),所以采用每次只处理当前文件的方式更合适。 因此,我们采用: - 在handleChange中,当文件状态为'ready'(新增文件)时,判断文件类型,如果符合,则将该文件加入uploadFileList(通过push方法)。 - 对于其他状态(如上传成功、失败等),我们不需要处理,因为文件类型已经确定,而且我们可能还需要显示上传状态。 但是,这里有一个关键:我们如何知道文件删除了?因为删除文件时,change事件也会触发,并且file.status会变成'removed'。此时,我们需要从uploadFileList中移除该文件。 所以,完整的handleChange函数需要处理两种情况: 1. 新增文件(status为'ready'):校验类型,合法则加入列表,不合法则忽略。 2. 删除文件(status为'removed'):从uploadFileList中移除该文件。 这样,我们就能保证文件列表的同步。 文件类型校验: - 我们可以通过file对象的type属性(MIME类型)或者通过文件名后缀来判断。这里我们使用后缀名判断,因为MIME类型可能不可靠。 - 假设我们只允许上传图片(png, jpg, jpeg),则可以定义允许的后缀列表:['.png', '.jpg', '.jpeg'],然后检查file.name的后缀是否在列表中。 注意:file对象有一个raw属性,它是原生的File对象,我们可以通过File对象的name属性获取文件名。 代码结构: 在Vue3的setup中: import { ref } from 'vue'; const uploadFileList = ref([]); const handleChange = (file, fileList) => { // 注意:这里fileList参数是当前组件内部的文件列表(包括所有状态),但我们不直接使用它,而是使用我们自己的uploadFileList // 我们只根据file的状态进行处理 if (file.status === 'ready') { // 检查文件类型 const allowedTypes = ['.png', '.jpg', '.jpeg']; const fileName = file.name; const fileExtension = fileName.substring(fileName.lastIndexOf('.')).toLowerCase(); if (allowedTypes.includes(fileExtension)) { // 符合类型,加入uploadFileList // 注意:这里我们不需要手动加入,因为el-upload组件会自动将文件加入它的内部列表,然后触发change事件,但是我们已经绑定了file-list为uploadFileList,所以我们需要自己维护。 // 实际上,在change事件触发时,组件内部已经将文件加入到了它的临时列表,但因为我们使用了:file-list="uploadFileList",所以显示的是uploadFileList。所以我们需要在这里将文件加入uploadFileList。 // 为了避免重复,我们检查一下uploadFileList中是否已经有了这个文件(根据uid) const index = uploadFileList.value.findIndex(f => f.uid === file.uid); if (index === -1) { uploadFileList.value.push(file); } } // 不符合类型,我们不做任何操作,这样就不会显示 } else if (file.status === 'removed') { // 文件被移除,从uploadFileList中删除 const index = uploadFileList.value.findIndex(f => f.uid === file.uid); if (index !== -1) { uploadFileList.value.splice(index, 1); } } } 但是,上述方法在文件上传过程中,如果文件状态变为其他(如'uploading'、'success'、'error'),我们并没有处理。实际上,我们不需要处理这些状态,因为文件已经存在于列表中,我们只控制文件的显示(即只显示符合类型的文件),而上传状态的变化由组件自己处理,我们只需要更新文件对象的状态即可。但是,注意我们自己的uploadFileList中也需要更新文件的状态,因为当文件状态变化时,change事件会触发,并且file对象的状态会更新,但是我们的uploadFileList中还是旧的状态。所以,我们需要在每次change事件时更新uploadFileList中对应文件的状态。 然而,这样处理会变得复杂。因此,我们考虑另一种更简单的方法:在每次change事件触发后,我们根据fileList(change事件的第二个参数)来更新我们的uploadFileList,但只保留符合类型且不是被移除的文件同时,对于新增的文件,我们也要过滤类型。 具体做法: const handleChange = (file, fileList) => { // 首先,过滤掉类型不符合且状态为ready的文件(实际上,我们可以在过滤条件中直接排除不符合类型的文件,不管状态如何,因为不符合类型的文件我们一直都不想要) // 但是,注意:已经在上传列表中的文件,如果类型不符合,我们应该在之前就已经过滤掉了,所以这里我们只需要对整个fileList进行过滤,保留类型符合的文件(注意:被移除的文件会自动从fileList中消失,所以我们不需要额外处理移除) // 然而,这里有一个问题:fileList参数是组件内部当前的文件列表(包括所有状态),但是当我们过滤后,可能会丢失一些状态(比如上传进度)。所以,我们想要保留除了不符合类型以外的所有文件及其状态。 // 因此,我们这样处理:我们遍历fileList,如果文件的状态是'ready'(新增)且类型不符合,我们就过滤掉;对于其他状态的文件,我们保留(因为已经通过了类型检查,或者是之前上传的)。 // 但是,这样会有一个漏洞:如果用户先选择了一个符合类型的文件,然后又选择了一个不符合类型的文件,那么不符合类型的文件也会出现在fileList中(状态为ready),我们需要在过滤时去掉。 // 所以,我们重新定义:我们只保留类型符合的文件,不管它是什么状态(除了被移除的状态,因为被移除的文件不会出现在fileList中)。 // 注意:被移除的文件不会出现在fileList参数中,所以不需要我们处理。 // 因此,我们可以这样: const filteredList = fileList.filter(f => { // 如果文件状态是'ready'(新增),则检查类型;如果不是'ready',说明是之前已经通过检查的文件(或者是上传中的文件等),我们保留。 if (f.status === 'ready') { const allowedTypes = ['.png', '.jpg', '.jpeg']; const fileName = f.name; const fileExtension = fileName.substring(fileName.lastIndexOf('.')).toLowerCase(); return allowedTypes.includes(fileExtension); } return true; // 非ready状态的文件都保留 }); // 然后,将过滤后的列表赋值给uploadFileList uploadFileList.value = filteredList; } 但是,这种方法在每次change事件时都会对整个文件列表进行过滤,可能会引起性能问题(尤其是文件很多时),而且可能会丢失一些状态?实际上,我们直接替换整个列表,每个文件对象还是原来的,所以状态不会丢失。 然而,需要注意的是,el-upload组件要求file-list是响应式的,并且我们这样赋值,组件会重新渲染。但这是可以接受的。 而且,这种方法简单明了,可以确保文件列表中只有符合类型要求的文件。 但是,我们还需要注意:当文件上传过程中,状态变化(如从ready变成uploading)也会触发change事件,此时我们再次过滤,但此时文件状态已经不是ready了,所以不会被过滤掉。所以,这个方法是可行的。 因此,我们采用第二种方法。 优化:我们可以将文件类型检查提取为一个函数。 代码: const allowedTypes = ['.png', '.jpg', '.jpeg']; const checkFileType = (file) => { const fileName = file.name; const fileExtension = fileName.substring(fileName.lastIndexOf('.')).toLowerCase(); return allowedTypes.includes(fileExtension); }; const handleChange = (file, fileList) => { // 过滤文件列表:只保留类型符合的文件(对于ready状态的文件进行类型检查,非ready状态的我们已经认为它是符合的,因为之前已经通过了检查) // 但是,这里有一个问题:如果用户通过修改DOM等方式强行添加了一个不符合类型的文件,并且状态不是ready,那么它也会被保留。不过正常情况下不会出现这种情况。 // 更严格的做法是:不管文件状态是什么,都检查类型。但是,对于已经在上传或者上传成功的文件,我们可能不想因为类型不符合而突然移除(这样会让用户困惑)。所以,我们只对新增的文件(ready)进行类型检查。 // 因此,我们按照上述逻辑:只过滤掉状态为ready且类型不符合的文件。 const filteredList = fileList.filter(f => { if (f.status === 'ready') { return checkFileType(f); } return true; }); uploadFileList.value = filteredList; } 但是,这样处理有一个问题:当用户选择多个文件时,其中有一个文件不符合类型,那么符合类型的文件会被多次添加到uploadFileList中吗?不会,因为每次change事件都会对整个fileList进行过滤,然后赋值给uploadFileList,所以最终列表是完整的。 另外,注意:el-upload组件要求我们使用:file-list绑定uploadFileList,这样我们更新uploadFileList,组件就会更新。 模板代码示例: <el-upload multiple :file-list="uploadFileList" :auto-upload="false" <!-- 如果不需要自动上传,设置为false --> @change="handleChange" > <!-- 其他内容,比如上传按钮 --> </el-upload> 但是,我们还需要注意:当用户选择文件时,如果选择了不符合类型的文件,我们希望给出提示。可以在过滤时,如果发现不符合类型的文件,就弹出一个消息。 改进handleChange函数: const handleChange = (file, fileList) => { // 首先,找出当前新增的不符合类型的文件(可能有多个,但每次change事件通常只处理一个文件,但fileList包含所有) // 我们可以在过滤的同时,收集不符合类型的文件(只针对ready状态) const invalidFiles = []; const filteredList = fileList.filter(f => { if (f.status === 'ready') { const valid = checkFileType(f); if (!valid) { invalidFiles.push(f.name); } return valid; } return true; }); if (invalidFiles.length > 0) { // 提示用户 ElMessage.error(`文件${invalidFiles.join(',')}类型不符合要求,已自动过滤`); } uploadFileList.value = filteredList; } 这样,当有文件被过滤掉时,用户会得到提示。 总结: - 使用el-upload组件,设置multiple支持多选。 - 使用:file-list绑定一个响应式数组(uploadFileList)来控制文件列表- 绑定@change事件,在事件处理函数中过滤文件列表:只保留新增时(status为ready)符合类型的文件,并更新uploadFileList。 - 对于不符合类型的新增文件,给出提示。 注意:auto-upload设置为false,这样文件不会自动上传,我们可以手动控制上传(如果需要上传的话)。 另外,如果需要上传,我们可以通过el-upload的ref来手动上传,或者使用http-request覆盖默认的上传行为。 完整示例代码(Vue3 + Element Plus):</think>在 Vue3 中使用 Element Plus 的 `el-upload` 组件时,可以通过以下方案实现文件类型校验、过滤不符合条件的文件,并支持多选功能: ### 完整实现方案 ```vue <template> <el
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值