el-upload手动控制上传多文件校验和文件删除

本文介绍了如何使用Element UI的el-upload组件改造为多文件手动上传,并添加文件类型和大小校验以及删除功能。通过设置`auto-upload=false`和`multiple`属性实现多文件选择,利用`on-change`回调进行文件校验,不合法的文件将被移除。在提交表单时,统一调用自定义上传方法批量上传文件,减少服务器IO操作。同时,文章还展示了相关的CSS样式调整,以展示文件略缩图和删除图标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前写过一篇关于el-upload单文件自定义上传文章: axios+elementui的upload使用http-request自定义文件上传_Suk_阿硕的博客-优快云博客_http-request自定义文件上传<!-- 关于组件的部分属性: action:上传的地址,和axios没关系,elementui自己发请求 :show-file-list:是否显示上传的文件列表 :on-success:上传成功的回调 :on-error:上传失败的回调 :before-upload:上传之前的回调,可以在这里检测文件类型和大小,还可以给额外参数赋值要带到服务器的数据 i...https://blog.youkuaiyun.com/Suk__/article/details/114229334

 之前的逻辑比较简单 直接单文件选一张上传一张,没有文件类型限制,也没有删除,现在需求是表单提交时上传所有选中的文件,而不是选中一张上传一张,并且有文件校验和删除功能,咱一步一步来实现:

1.文件略缩图带删除交互实现:

文件上传部分模板代码: 

<el-form-item label="上传附件" prop="attachments">
                <el-upload ref="uploadRef" :on-change="onUploadChange" multiple class="upload-attachments"
                    :auto-upload="false" action="#" list-type="picture-card">
                    <i slot="default" class="el-icon-plus"></i>
                    <div slot="file" class="upload-item" slot-scope="{file}">
                        <span class="doc-name" v-if="isFileTypeOfDoc(file)">{{ file.name }}</span>
                        <div v-else class="upload-img-wrapper">
                            <img class="el-upload-list__item-thumbnail" :src="file.url">
                        </div>
                        <i @click="onRemoveFile(file)" class="delete-icon">×</i>
                    </div>
                </el-upload>
            </el-form-item>
            <p class="desc">仅支持jpg、png、jpeg、doc格式,文件大小5M以内</p>

组件的props需要指定的有:

auto-upload: false 取消自动上传 不会已选中就上传

multiple 允许同时选中多个文件

list-type: picture-card 列表视图展示略缩图

on-change: 文件列表状态发生改变的回调,比如你选中文件上传了就会触发

action: '#' 这个是上传文件的接口地址 我们自定义手动上传就不写这个 写个#就行 

样式:

// 附件上传
    .upload-attachments {
        ::v-deep .el-upload-list--picture-card {
            display: inline-flex;
        }

        ::v-deep .el-upload-list__item {
            width: 62px;
            height: 62px;
            border: none; // 去掉外层的边框

            // el-upload-list__item略缩图边框大小
            &.is-ready {
                overflow: visible; // 不能挡住删除icon

                // 略缩图大小
                .upload-item {
                    position: relative;
                    width: 62px;
                    height: 62px;
                    border-radius: 4px;
                    border: 1px solid #c0ccda;

                    .doc-name {
                        position: absolute;
                        top: 50%;
                        width: 62px;
                        transform: translateY(-50%);
                        text-align: center;
                        color: $contentColor;
                    }

                    .upload-img-wrapper {
                        width: 60px;
                        height: 60px;

                        img {
                            border-radius: 4px; //圆角图片
                        }
                    }

                    .delete-icon {
                        position: absolute;
                        top: -7px;
                        right: -7px;
                        width: 14px;
                        height: 14px;
                        line-height: 14px;
                        background-color: $mainColor;
                        color: #fff;
                        text-align: center;
                        border-radius: 7px;
                        cursor: default;
                    }
                }



            }
        }

        .el-upload {

            // 上传卡片按钮大小
            ::v-deep &.el-upload--picture-card {
                width: 62px;
                height: 62px;
                line-height: 62px;

                i {
                    font-size: 14px;
                }
            }
        }
    }

效果:

 讲讲模板部分,首先使用的是el-upload组件的file插槽,自定义上传后文件的略缩图列表展示样式,默认没有上传文件时显示+号,定位了一个删除的icon在每个文件的右上角

这里因为除了图片还要支持doc文档格式,所以根据文件名后缀判断了文件类型来分别展示文件名和图片:

 然后就是删除功能,就是通过ref拿到upload组件实例调用了组件handleRemove方法传入要删除的file即可

       /**
         * @description 删除文件
         */
        onRemoveFile(file) {
            const index = this.$refs.uploadRef.uploadFiles.findIndex(e => e.uid === file.uid);
            this.$refs.uploadRef.uploadFiles.splice(index, 1);
        },

el-upload组件内部维护了一个上传的文件集合,因为是自定义手动上传,所以选择后是没有马上上传的,file对象存在组件内部的uploadFiles这个数组中:

在每次文件列表发生变化时,我们可以在on-change回调中校验上传的文件大小和类型是否合法:

        /**
         * @description 用户选择文件后对文件进行校验
         */
        onUploadChange(file) {
            const fileType = file.raw.type;
            const fileSize = file.size / 1024 / 1024;
            if (!AllowedUploadFileType.includes(fileType)) {
                Notification({
                    type: 'warning',
                    message: '非法的文件类型',
                    duration: 3000
                })
                this.$refs.uploadRef.handleRemove(file)
                return;
            }
            if (fileSize > 5) {
                Notification({
                    type: 'warning',
                    message: '文件大小不能超过5M',
                    duration: 3000,
                })
                this.$refs.uploadRef.handleRemove(file)
                return;
            }
        },

如果不合法就从数组中删除掉这个文件,就能达到校验上传的文件的目的了.

最后就是点击确认提交表单时统一上传所有文件然后拿到后端返回的文件绝对路径进行提交表单:

/**
         * @description 确认提交
         */
        onConfirm() {
            this.$refs.form.validate(async (isValid) => {
                if (!isValid) {
                    return;
                }
                this.setLoading({
                    type: 'confirmLoading',
                    payload: true
                })
                try {
                    // 先上传附件得到附件地址
                    const readyUploadFiles = this.$refs.uploadRef.uploadFiles;
                    if (readyUploadFiles.length) {
                        const fileUrls = await this.fetchBatchUpload(readyUploadFiles);
                        this.formData.attachments = fileUrls;
                    }
                    // 提交反馈
                    const response = await feedbackAPI.userFeedbackSubmit(this.formData);
                    if (response.success) {
                        this.$refs.form.resetFields();
                        this.$refs.uploadRef.clearFiles();
                        Object.assign(this.formData, this.$options.data().formData);
                        this.$message({
                            type: 'success',
                            message: '操作成功',
                            duration: 3000
                        });
                        this.onClose();
                    }
                } catch (error) {
                    this.$message({
                        type: 'error',
                        message: `提交用户反馈失败!错误的堆栈信息${error.stack}`,
                        duration: 5000
                    });
                } finally {
                    this.setLoading({
                        type: 'confirmLoading',
                        payload: false
                    })
                }
            });
        },
        /**
         * @description 请求批量上传
         * @param {Array<File>} files 已选择的文件列表
         */
        async fetchBatchUpload(files) {
            const formData = new FormData();
            for (const file of files) {
                formData.append('files', file.raw);
            }
            formData.append('type', 'feedback');
            const response = await feedbackAPI.uploadBatch(formData);
            return response.data;
        },

因为接口采用的formData 上传类型上axios上传配置项里需要修改一下Content-Type为multiplepart:

最后formData在append同一个key时不会覆盖掉已有的,在内部会处理成一个数组,也就是上面收集上传文件的参数时append这个files字段可以多次append的原因,http协议对请求头'Content-Type': 'multipart/form-data'的处理就是这样,我们看下请求报文中的显示:

  

多文件上传时,使用手动上传的好处就是可以节省服务器io操作和请求次数,只有最终提交表单时发送一次上传请求,但是后端接口要支持多文件,然后服务器也不会因为上传文件后不往下继续操作了导致直接上传的无用文件占用磁盘临时文件夹空间和写入磁盘的io消耗.

又要一点了 因为很累又困 写的很粗糙比较赶 算是记录一下这次上传需求吧,睡觉😴

<think>好的,用户想了解如何使用element-ui的el-upload组件实现手动上传文件的功能。我需要先回忆el-upload的相关属性和方法。根据引用[3],auto-upload属性控制是否自动上传,默认是true。所以第一步应该是设置auto-upload为false,这样选择文件后不会自动上传。 然后,用户需要手动触发上传,这时候应该用到组件的submit方法。根据文档,需要通过ref来获取组件实例,然后调用submit()。例如,在模板里给el-upload添加ref="upload",然后在方法里用this.$refs.upload.submit()来触发上传。 接下来,可能需要处理上传的参数。用户提到在before-upload中传其他参数,但根据引用[3],如果在before-upload返回false或者Promise被reject,会停止上传。所以如果需要添加额外参数,可以在before-upload中处理,或者使用data属性动态设置。 另外,上传过程中的进度和成功回调需要绑定对应的事件处理函数,比如on-progress和on-success。引用[2]中提到的handleFileUploadProgress和handleFileSuccess就是用来处理这些情况的。 还要注意文件校验的问题,引用[4]提到必选项校验的问题,可能在手动上传时需要在前端先做校验,比如检查文件类型、大小等,通过后再触发上传。 最后,需要提供一个示例代码,展示如何将这些属性和方法结合起来。确保代码中的auto-upload设置为false,添加ref,以及手动上传的按钮触发submit方法。同时,上传地址action需要正确设置,可能还需要处理跨域问题。 总结步骤:设置auto-upload为false,添加ref,手动调用submit,处理上传参数和回调事件。这样用户就可以实现手动上传的功能了。</think>### 如何通过 el-upload 实现手动上传文件的功能? 在 Element UI 中,`el-upload` 组件默认会自动上传文件(通过设置 `auto-upload` 属性为 `true`)。若需手动触发上传,需以下步骤实现: --- #### **1. 关闭自动上传** 将 `auto-upload` 属性设为 `false`,阻止选取文件后自动上传: ```html <el-upload ref="upload" :auto-upload="false" action="/api/upload" :on-success="handleSuccess" :on-error="handleError"> <el-button slot="trigger">选择文件</el-button> <el-button @click="submitUpload">手动上传</el-button> </el-upload> ``` --- #### **2. 手动触发上传** 通过 `ref` 获取组件实例,调用其 `submit()` 方法触发上传: ```javascript export default { methods: { submitUpload() { this.$refs.upload.submit(); // 手动提交上传 }, handleSuccess(response, file) { console.log("上传成功", response); }, handleError(err, file) { console.error("上传失败", err); } } }; ``` --- #### **3. 动态设置上传参数** 若需动态添加参数(如用户输入),可通过 `data` 属性或 `before-upload` 钩子: ```html <el-upload :data="{ userId: 123 }" :before-upload="beforeUpload"> </el-upload> ``` ```javascript methods: { beforeUpload(file) { // 返回 Promise 可控制上传行为 return new Promise((resolve, reject) => { if (file.size > 10 * 1024 * 1024) { this.$message.error("文件过大"); reject(false); } else { resolve(true); } }); } } ``` --- #### **4. 文件校验与状态管理** 通过 `on-change` 事件监听文件状态变化,实现前端校验: ```html <el-upload :on-change="handleFileChange"> </el-upload> ``` ```javascript methods: { handleFileChange(file, fileList) { if (file.status === 'ready') { // 校验逻辑 if (!file.name.endsWith('.pdf')) { this.$message.error("仅支持 PDF 文件"); fileList.pop(); // 移除不符合条件的文件 } } } } ``` --- #### **注意事项** 1. **跨域问题**:确保后端接口支持跨域请求(CORS 配置)[^3]。 2. **上传进度**:通过 `on-progress` 事件可监听上传进度[^2]。 3. **文件覆盖**:设置 `limit` 属性可限制上传文件数量,结合 `on-exceed` 处理超额情况[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值