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

33 篇文章 1 订阅
12 篇文章 0 订阅

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

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

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在使用 element-ui 的 el-upload 组件时,可以通过设置 accept 属性来限制上传文件类型。accept 属性可以接受一个字符串,用于指定可接受的 MIME 类型或文件扩展名。 例如,如果你只想允许上传图片文件,可以这样设置: ``` <el-upload class="upload-demo" action="/upload" :accept="'image/*'" :on-success="handleSuccess" :before-upload="beforeUpload"> <el-button size="small" type="primary">点击上传</el-button> </el-upload> ``` 上面的代码中,accept 属性的值为 `image/*`,表示只接受 MIME 类型为 image 开头的文件。你也可以使用具体的 MIME 类型或文件扩展名来限制文件类型,例如: - `image/png`:只接受 PNG 格式的图片文件。 - `.jpeg,.jpg,.png`:只接受扩展名为 jpeg、jpg 或 png 的图片文件。 需要注意的是,accept 属性并不是绝对可靠的,因为用户可以手动修改文件的 MIME 类型或扩展名。因此,你在后端也需要对上传文件类型进行校验。 ### 回答2: el-upload是基于Element UI开发的文件上传组件,可以方便地实现文件上传和预览功能。 在el-upload组件中,可以通过设置属性accept来限制文件的类型。accept属性的值可以是一个字符串或者一个字符串数组。当属性值为字符串时,表示限制上传文件类型为指定的单一类型;当属性值为字符串数组时,表示限制上传文件类型为指定的多个类型中的任意一种。 例如,如果我们想要限制只能上传图片类型的文件,我们可以这样设置accept属性: <el-upload accept="image/*" action="/upload" :before-upload="beforeUpload" > <el-button size="small" type="primary">点击上传</el-button> </el-upload> 上述代码中,accept属性的值为"image/*",表示只能上传图片类型的文件。"image/*"是一个通配符,表示允许上传以"image/"开头的文件类型,例如"image/png"、"image/jpeg"等。 如果我们想要限制只能上传图片和视频类型的文件,我们可以这样设置accept属性: <el-upload :accept="['image/*', 'video/*']" action="/upload" :before-upload="beforeUpload" > <el-button size="small" type="primary">点击上传</el-button> </el-upload> 上述代码中,accept属性的值为一个字符串数组,包含两个元素"image/*"和"video/*",表示只能上传以"image/"开头或者以"video/"开头的文件类型,即图片和视频类型的文件。 通过设置accept属性,我们可以灵活地限制el-upload组件的文件类型,以满足我们的需求。 ### 回答3: el-uploadElement UI 中的上传组件,用于实现文件上传功能。它提供了很多参数和选项来限制上传文件类型。 首先,el-upload 组件通过设置 accept 属性来限制文件类型。可以通过设置 accept 属性为特定的文件扩展名或 MIME 类型来限制上传文件类型。例如,设置 accept 属性为 "image/*" 可以只允许上传图片文件,设置为 "video/*" 可以只允许上传视频文件。 其次,el-upload 组件还可以通过设置 before-upload 属性来对文件进行进一步的限制。before-upload 属性接收一个函数,该函数会在文件上传之前被调用。在该函数中,我们可以通过判断文件的类型、大小等属性来决定是否继续上传。如果函数返回 false,则上传被中断,文件不会被上传。 除了以上两种方式,el-upload 还提供了其他一些属性和事件来限制文件类型。例如,通过设置 limit 属性可以限制一次只能上传文件数量;通过设置 on-exceed 属性可以限制文件数量超过限制时的行为;通过设置 file-list 属性可以限制同时显示的文件数量。 总的来说,el-upload 提供了多种方式来对文件类型进行限制,可以通过设置 accept 属性、before-upload 属性、limit 属性等来满足不同的需求,并实现对文件上传的精确控制和限制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值