vue elementUI文件上传实例

本文深入解析了一个基于Element UI的文件上传组件实现细节,包括图片和文档的上传、预览、格式与大小限制、异步上传及后端接口交互。通过具体代码示例,展示了如何进行文件格式验证、大小检查、上传进度跟踪以及错误处理。
 <!--图片,文件的上传与图片展示-->
 <el-upload
          class="upload-demo"
          ref="upload"
          action=""
          :on-preview="handlePreview"
          :on-remove="imgRemove"
          :on-change="changeState"
          list-type="picture-card"
          :show-file-list="true"
          :file-list="imgfileList"
          :auto-upload="false">
          <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
          <!--        <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload"
                             v-if="newFile.length!==0">开始上传
                  </el-button>-->
          <div slot="tip" class="el-upload__tip" :style="'color:'+color">{{errorMessage}}</div>
          <el-dialog :visible.sync="dialogVisible" :modal="false">
            <img height="60%" width="100%" :src="dialogImageUrl" alt="">
          </el-dialog>
        </el-upload>
 <!--文件展示-->
        <el-upload
          class="upload-demo"
          ref="upload2"
          action=""
          :on-remove="fileRemove"
          list-type="text"
          :on-preview="handleFile"
          :show-file-list="true"
          :file-list="fileList"
          :auto-upload="false">
        </el-upload>

 

        data() {
            return {
                imgUrl:'',//预览地址
                imgTitle:'',
                isShowImg:false,
              
                newFile: [],//新增图片的缓存
                color: '#000000',//错误提示颜色
                fileUrl: '',//预览文件的地址
                fileList: [],//文件集合
                imgfileList: [],//图片集合
                base64List: [],//base64集合
                dialogVisible: false,//文件预览窗口状态
                dialogImageUrl: '',   //预览图片的地址
                errorMessage: '只能上传图片,文档等类型文件,且文件大小不能超过50M'
            }

 

   methods: {
            
 
            //todo 图片增加钩子
            changeState(file, fileList) {
                let that = this
                //文件格式[通用算法]
                let str = file.name.split('').reverse().join('');
                let format = str.substring(0, str.indexOf(".")).split('').reverse().join('')
                const imgType = ['jpeg', 'jpg', 'png', 'bmp', 'gif', 'tif', 'tga', 'ico']
                const fileType = ['pdf', 'txt', 'xlsx', 'xls', 'doc', 'docx', 'pptx', 'ppt', 'rar', 'zip', 'z7']
                let isFormat = false
                let formatArr = imgType.concat(fileType)
                for (let i = 0; i < formatArr.length; i++) {
                    if (fileType.concat(imgType)[i] === format) {
                        isFormat = true;
                    }
                }
                if (isFormat === false) {
                    this.$notify({
                        title: '不支持该格式 !',
                        showClose: false,
                        duration: 3000,
                        offset: 100
                    });
                    this.imgfileList.push(file)
                    this.fileList.push(file)
                    this.imgfileList.splice(this.imgfileList.length - 1, 1)
                    this.fileList.splice(this.fileList.length - 1, 1)
                    this.color = "#FF0000"
                    setTimeout(function () {
                        that.color = "#000000"
                    }, 4000)
                    return
                }
                const isLt4M = 50;
                //todo 文件大小判断
                if (file.size / 1024 / 1024 > isLt4M) {
                    this.imgfileList.push(file)
                    this.fileList.push(file)
                    this.$notify({
                        title: '文件不能大于50M !',
                        showClose: false,
                        duration: 3000,
                        offset: 100
                    });

                    this.imgfileList.splice(this.imgfileList.length - 1, 1)
                    this.fileList.splice(this.fileList.length - 1, 1)
                    this.color = "#FF0000"
                    let that = this
                    setTimeout(function () {
                        that.color = "#000000"
                    }, 4000)
                    return
                }
                //todo 文件格式判断  【图片格式】
                for (let i = 0; i < imgType.length; i++) {
                    if (imgType[i].toLowerCase() === format.toLowerCase()) {
                        this.imgfileList.push(file)  //仅展示
                        //this.newFile = this.fileFilter()//显示按钮
                        //this.submitUpload()//上传
                        this.fileToBase64(file)
                    }
                }
                //todo 文件格式判断  【非图片格式】
                for (let i = 0; i < fileType.length; i++) {
                    if (fileType[i].toLowerCase() === format.toLowerCase()) {
                        this.fileList.push(file)//仅展示
                        this.imgfileList.push(file)
                        this.imgfileList.splice(this.imgfileList.length - 1, 1)
                        //this.newFile = this.fileFilter()//显示按钮
                        //this.submitUpload()//手动上传
                        this.fileToBase64(file)

                    }
                }

            },

            //todo 图片视图
            handlePreview(file) {
                this.dialogImageUrl = file.url;
                this.dialogVisible = true;
            },
            //todo 图片移除回调
            imgRemove(file, fileList) {
                this.base64List = []//清空沉积物
                this.imgfileList = fileList
                this.executeDeleteFile(file)
            },
            //todo 文件移除回调
            fileRemove(file, fileList) {
                this.base64List = []//清空沉积物
                this.fileList = fileList
                //this.newFile = this.fileFilter()//显示按钮
                this.executeDeleteFile(file)
            },


            //todo 执行删除文件【连接后端接口】
            executeDeleteFile(condition) {
                order_api.fileDelete(condition).then(response => {
                    this.refreshFileList()
                    this.$notify({
                        title: '已删除 ' + " " + condition.name + " ",
                        showClose: false,
                        duration: 2000,
                        offset: 100
                    });
                }).catch(error => {
                    //window.location.reload();
                })

            },

            //todo 自动上传
            fileToBase64(file) {
                let that = this
                let str = file.name.split('').reverse().join('');
                let fileFormat = str.substring(0, str.indexOf(".")).split('').reverse().join('')//文件格式
                let fileName = file.name//文件名
                let ordersData = that.orderData;//当前订单数据
                let reader = new FileReader();
                reader.readAsDataURL(file.raw)
                reader.onload = function (e) {
                    let base = e.target.result;
                    const loading = that.$loading({
                        lock: true,
                        text: '正 在 上 传. . .',
                        spinner: 'el-icon-loading',
                        background: 'rgba(0, 0, 0, 0.76)'
                        //loading.close();
                    });
                    order_api.fileUpload({
                        name: fileName,
                        type: fileFormat,
                        base64: base
                    }, ordersData).then(response => {
                        loading.close();

                       // if (ordersData.imgNumber===null||ordersData.imgNumber===''){     //todo 只刷一次
                            //调用接口,刷新当前订单数据
                            order_api.findOrderOwnInfo(ordersData).then(response => {
                                const data = response.data.data.data
                                that.ExpIstData = data.instrumentData
                                that.OrderTypeData = data.OrderTypeData
                                that.orderData = data.ordersData
                                that.laborData = data.laboratoryData
                                that.orderQuantity = data.orderQuantity

                            })
                       // }

                        setTimeout(function () {
                            that.refreshFileList()//刷新图片列表
                            that.$notify({
                                title: '已添加 ' + " " + fileName + " ",
                                showClose: false,
                                duration: 2000,
                                offset: 100
                            });
                        }, 200)

                    }).catch(error => {
                        loading.close();
                        setTimeout(function () {
                            that.refreshFileList()
                            that.$notify({
                                title: '请求超时,请重试 !',
                                showClose: false,
                                duration: 2000,
                                offset: 100
                            });
                        }, 200)
                        //window.location.reload();
                    })
                }
            },
            //todo 点击文件
            handleFile(file) {
                location.href = file.url;
            },

            //todo 刷新已上传文件列表
            refreshFileList() {
                this.imgfileList = []
                this.fileList = []
                order_api.refreshFileList(this.orderData).then(response => {
                    const data = response.data.data.data.imgData
                    const imgType = ['jpeg', 'jpg', 'png', 'bmp', 'gif', 'tif', 'tga', 'ico']
                    const fileType = ['pdf', 'txt', 'xlsx', 'xls', 'doc', 'docx', 'pptx', 'ppt', 'rar', 'zip', 'z7']
                    //todo 文件信息回填
                    for (let i = 0; i < data.length; i++) {
                        let imgNumber = data[i].imgNumber
                        let url = data[i].imgUrl
                        let name = data[i].fileName
                        let id = data[i].id
                        let str = url.split('').reverse().join('');
                        let format = str.substring(0, str.indexOf(".")).split('').reverse().join('')
                        for (let i = 0; i < imgType.length; i++) {
                            if (imgType[i].toLowerCase() === format.toLowerCase()) {//属于图片
                                this.imgfileList.push({id, name, url, imgNumber})
                            }
                        }
                        for (let i = 0; i < fileType.length; i++) {
                            if (fileType[i].toLowerCase() === format.toLowerCase()) {//属于文件
                                this.fileList.push({id, name, url, imgNumber})
                            }
                        }
                    }
                }).catch(error => {

                })
            },

     //todo 过滤掉已上传的文件  【手动上传时启用】
            fileFilter() {
                let imgList = []
                let files = []
                //todo 过滤掉已上传的文件
                if (this.imgfileList.length !== 0) {
                    for (let i = 0; i < this.imgfileList.length; i++) {
                        if (this.imgfileList[i].status === "ready") {
                            imgList.push(this.imgfileList[i])
                        }
                    }
                }
                //todo 过滤掉已上传的文件
                if (this.fileList.length !== 0) {
                    for (let i = 0; i < this.fileList.length; i++) {
                        if (this.fileList[i].status === "ready") {
                            files.push(this.fileList[i])
                        }
                    }
                }
                return imgList.concat(files)
            },
            //todo 开始上传  【暂时不用手动上传】
            submitUpload() {
                console.log("图片", this.imgfileList, "文件", this.fileList)
                let that = this
                that.base64List = []//清空沉积物
                var list = [];
                let fileList = this.newFile = this.fileFilter()//显示按钮
                for (let i = 0; i < fileList.length; i++) {
                    let str = fileList[i].name.split('').reverse().join('');
                    let fileFormat = str.substring(0, str.indexOf(".")).split('').reverse().join('')//文件格式
                    let fileName = fileList[i].name//文件名
                    var reader = new FileReader();
                    reader.readAsDataURL(fileList[i].raw)
                    /*               //todo 错误写法1  【这种写法理论上正确,但最终,list是空值】
                                     var base=''
                                     reader.onload = function () {
                                         base = e.target.result;
                                         list.push({name: fileName, type: fileFormat, base64: base})
                                     };
                                     //todo 错误写法2  【这种写法理论上正确,但最终,list中的base64是空值】
                                     reader.onload = (e) => {
                                         var base = e.target.result;
                                         list.push({name: fileName, type: fileFormat, base64: base})
                                     }*/
                    //todo 正确写法
                    reader.onload = function (e) {
                        var base = e.target.result;
                        that.base64List.push({name: fileName, type: fileFormat, base64: base})
                        if (i === fileList.length - 1) {//解决异步问题
                            start()
                        }
                    }
                }

                function start() {
                    list = that.base64List
                    let ordersData = that.ordersData;
                        order_api.fileUpload({list,ordersData}).then(response => {
                        }).catch(error => {
                            //window.location.reload();
                        })
                }
            },

        },

 

### 实现 Vue3 和 ElementUI 表单文件上传 为了在 Vue3 项目中使用 ElementUI 实现表单文件上传功能,可以遵循以下方法: #### 安装依赖库 首先,在项目中安装 `element-plus` 库作为 ElementUIVue3 版本支持。 ```bash npm install element-plus ``` #### 创建组件结构 创建用于展示和管理文件上传的模板部分。这里采用了一个简单的布局来放置上传组件,并定义了必要的事件处理器。 ```html <template> <el-form ref="formRef" :model="formData"> <!-- 文件上传控件 --> <el-upload action="/your/upload/endpoint" :on-preview="handlePreview" :on-remove="delFile" :file-list="files" list-type="text" multiple > <el-button type="primary">点击上传</el-button> </el-upload> <!-- 提交按钮 --> <el-button @click="submitForm(formRef)">提交</el-button> </el-form> </template> ``` #### 初始化数据与逻辑处理 接下来初始化页面所需的数据模型以及编写相应的业务逻辑函数。这部分代码主要负责监听用户的交互行为并作出响应。 ```javascript <script setup lang="ts"> import { reactive, ref } from 'vue'; import axios from 'axios'; // 数据绑定对象 const formData = reactive({ fileModels: [] }); // 存储已选中的文件列表 let files = ref([]); // 获取表单实例 const formRef = ref(null); async function submitForm(formEl) { if (!formEl) return; await formEl.validate((valid) => { if (valid) { // 处理表单提交逻辑... console.log('submit!'); } }); } function handlePreview(file) { console.log(`预览 ${file.name}`); } // 删除指定索引处的文件项 function delFile(file, fileList) { let index = files.value.indexOf(file); files.value.splice(index, 1); } </script> ``` 上述实现方式涵盖了基本的功能需求,包括但不限于多文件选择、文件移除操作等[^3]。值得注意的是,当涉及到实际服务器通信时,应当根据具体的 API 接口调整 `action` 属性指向的服务地址;同时也要注意跨域资源共享(CORS)策略配置等问题[^4]。 对于更复杂的场景,比如需要同步发送额外参数给服务端,则可以在发起 HTTP 请求之前手动构建 FormData 对象,并将其传递给自定义的 AJAX 方法完成整个流程。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值