Vue支持多文件上传 前端+后端 (详细介绍)

news/2024/5/5 19:39:48/文章来源:https://blog.csdn.net/songyinyi/article/details/126994028

前端vue+后端java支持多文件上传

  • 效果图
  • Vue部分
  • 后台部分

效果图

在这里插入图片描述
可以上传多个文件

Vue部分

<template><div><el-form-item label="案例名称" prop="caseName"><el-input v-model="formObj.caseName" placeholder="请输入案例名称"/></el-form-item><el-form-item label="适用问题类型" prop="questionType"><asp-dict dictCode="question_type" v-model="formObj.questionType"></asp-dict></el-form-item><el-form-item label="审计类型" prop="auditType"><asp-dict dictCode="audit_types" v-model="formObj.auditType"></asp-dict></el-form-item><el-form-item label="上传案例文档" prop="fileList"><el-uploadv-model="formObj.fileList"name="file":with-credentials="true":action="uploadAction":headers="headers":drag="drag":show-file-list="showFileList":file-list="fileList":disabled="disabled":before-upload="beforeUpload":on-change="handleChange":on-remove="handleRemove":on-preview="handlePreviewDl":on-progress="handleProcess"multiple><el-button size="small" type="primary">点击上传<i class="el-icon-upload el-icon--right"/></el-button><div  slot="tip" class="el-upload__tip">支持文件类型:.doc,.docx,.pdf,.jpg,.png,.xls,.xlsx</div></el-upload></el-form-item><el-form-item label="目录选择" prop="parentId"><tree-selectv-model="formObj.caseCatalogueId":options="treeData":normalizer="normalizer":show-count="true"placeholder="请选择目录"/></el-form-item></div>
</template><script>const uidGenerator = () => {return '-' + parseInt(Math.random() * 10000 + 1, 10)}const FILE_TYPE_ALL = 'all'const FILE_TYPE_IMG = 'image'const FILE_TYPE_TXT = 'file'import { getTreeList } from '@/api/catalogue/catalogueCase'// 导入 ASP 平台通用组件包import AspDev from '@/utils/aspdev'import TreeSelect from '@riophae/vue-treeselect'import '@riophae/vue-treeselect/dist/vue-treeselect.css'// 解构通用组件const {AspDict} = AspDevexport default {components: {AspDict,TreeSelect},name: 'caseForm',props: {formObj:{},text: {type: String,required: false,default: '点击上传'},prompt: {type: [String, Boolean],required: false,default: ''},fileType: {type: String,required: false,default: FILE_TYPE_ALL},fileSuffix: {type: String,required: false,default: ""},limitSize: {type: Number,required: false},/* 这个属性用于控制文件上传的业务路径*/bizPath: {type: String,required: false,default: 'temp'},limit: {type: Number,required: false},drag: {type: Boolean,required: false,default: false},showFileList: {type: Boolean,required: false,default: true},disabled: {type: Boolean,required: false,default: false},value: {type: [String, Array],required: false}},watch: {value(val) {this.initFileList(val)}},data() {return {uploadAction: window._CONFIG['BASE_URL'] + '/finance/case/upload', // 上传的文件服务器地址downloadAction: window._CONFIG['BASE_URL'] + '/common/download/resource?name=', // 文件下载服务器地址headers: {},fileList: [],treeData: [],// 树形对应defaultProps: {children: 'children',label: 'name',},}},created() {this.initFileList(this.value)//获取案例目录树形结构getTreeList(this.queryParams).then((response) => {this.treeData = response.data})},methods: {initFileList(arr) {if (!arr || arr.length === 0) {this.fileList = []return}var fileList = []for (var a = 0; a < arr.length; a++) {fileList.push({uid: uidGenerator(),name: arr[a].fileName,status: 'success',filePath: arr[a].filePath,url: `${this.downloadAction}${encodeURI(arr[a].filePath)}`,response: {status: 'history',url: `${this.downloadAction}${encodeURI(arr[a].filePath)}`}})}this.fileList = fileList},// 限制上传类型beforeUpload: function (file) {const fileType = file.type;const fileSize = file.size / 1024 / 1024;const fileSuffix = file.name.replace(/^.*(\.[a-z0-9]+)$/gi, "$1");if (fileType === FILE_TYPE_IMG) {if (fileType.indexOf('image') < 0) {this.msgError('请上传图片')return false}} else if (fileType === FILE_TYPE_TXT) {if (fileType.indexOf('image') >= 0) {this.msgError('请上传文件')return false}}if (this.fileSuffix && this.fileSuffix.indexOf(fileSuffix) < 0) {this.msgError('上传文件格式有误')return false}if (fileSize > this.limitSize) {this.msgError('超出上传大小限制')return false}this.$emit("beforeUpload", file);return true},handleChange(file, fileList) {if (file.status === 'success') {this.msgSuccess(`${file.name} 上传成功!`)fileList = fileList.map(file => {if (file.response && file.response.status !== 'history') {file.url = `${this.downloadAction}${encodeURI(file.response.filePath)}`file.filePath = file.response.filePath//TODO 这里处理为 接口返回地址 择以接口地址为准if(file.response.url) {file.url = file.response.url;}}return file})} else if (file.status === 'fail') {this.msgError(`${file.name} 上传失败.`)} else if (file.status === 'removed') {this.handleRemove(file)}this.fileList = fileListif (file.status === 'success') {this.handlePathChange()}},// 触发双向数据绑定数据handlePathChange() {const uploadFiles = this.fileListvar arr = []if (!uploadFiles || uploadFiles.length === 0) {arr = []}if (this.limit === 1) {arr.push({filePath: uploadFiles[uploadFiles.length - 1].filePath,name: uploadFiles[uploadFiles.length - 1].name,fileUrl: uploadFiles[uploadFiles.length - 1].url,})} else {for (var a = 0; a < uploadFiles.length; a++) {arr.push({filePath: uploadFiles[a].filePath,name: uploadFiles[a].name,fileUrl: uploadFiles[a].url,})}}this.formObj.fileList=arrthis.$emit('change', arr)},// 删除文件时handleRemove(file, fileList) {this.deleteFile(file.filePath).then(() => {this.fileList = fileListthis.handlePathChange()this.msgSuccess('文件删除成功')}).catch(() => {this.msgError('文件删除失败')})},handlePreviewDl(file) {this.download(file.filePath, true, file.name)},handleProcess(event, file, fileList) {this.$emit('process', {event, file, fileList});},normalizer(node) {if (node.children && !node.children.length) {delete node.children}return {id: node.caseCatalogueId,label: node.name,children: node.children,}},//回显文件echoFile(fileList){this.fileList=fileList},},model: {prop: 'value',event: 'change'}}
</script>
<style lang="scss" scoped>@import '@/assets/styles/table37.scss';
</style>

里面最主要的方法我认为是handleChange这方法,这个方法请求后台接口返回后台的响应值;uploadAction 去填写后台文件上传的接口请求;handlePathChange这个方法去给他触发双向数据绑定数据 最终拿到arr数组,然后我们吧这个数组赋值给我们的**v-model=“formObj.fileList”**然后去提交给后台统一保存 ;echoFile这个方法是为了每次打开新增清空和回显文件 这里我是这样调用的触发 的

/** 修改按钮操作 */handleUpdate(row) {this.reset()this.$nextTick(() => {this.$refs['formUpdate'].echoFile([])})const caseId = row.caseId || this.idsgetCase(caseId).then(res => {this.form = res.dataconst queryData = res.dataconst addRouterTem = this.addRouterthis.$nextTick(() => {this.$refs['formUpdate'].echoFile(res.data.fileList)})if (this.needTagsView) {this.open = truethis.title = '修改案例'} else {this.$router.push({'path': addRouterTem,'query': { formObj: queryData }})}})},

后台部分

这里用MultipartFile[] file 数组去接收多个文件

/*** 通用上传请求*/@PostMapping("/upload")public AjaxResult uploadFile(MultipartFile[] file) throws Exception{AjaxResult ajax = AjaxResult.success();try{for (MultipartFile f : file) {// 上传文件路径String filePath = AspDevConfig.getUploadPath();//配置文件yml文件填写的路径// 上传并返回新文件名称String fileName = FileUploadUtils.upload(filePath, f);String url = serverConfig.getUrl() + fileName;//页面访问的全路径ajax.put("name", f.getName());ajax.put("filePath", fileName);ajax.put("url", url);}return ajax;}catch (Exception e){return AjaxResult.error(e.getMessage());}}

批量上传多个文件我建议用两个表,一个用主表,一个用来存放文件详细的
在新增的时候互不影响存个主表id就行

 /*** 新增案例** @param tCase 案例* @return 结果*/@Override@Transactional(readOnly = false)public int insertTCase(TCase tCase) {String uuid = UUID.randomUUID().toString();tCase.setCreateBy(UserInfoUtil.getUserInfo().getUserID());tCase.setCreateTime(DateUtils.getNowDate());if (StringUtils.isEmpty(tCase.getCaseId())) {tCase.setCaseId(uuid);}List<TCaseFile> fileList = tCase.getFileList();fileList.forEach(t->{t.setCaseId(uuid);t.setFileId(UUID.randomUUID().toString());t.setCreateBy(UserInfoUtil.getUserInfo().getUserID());t.setCreateTime(DateUtils.getNowDate());tCaseFileMapper.insertTCaseFile(t);});return tCaseMapper.insertTCase(tCase);}

在修改文件的时候我采用的是把所有文件删除,然后在统一在添加上

/*** 修改案例** @param tCase 案例* @return 结果*/@Override@Transactional(readOnly = false)public int updateTCase(TCase tCase) {tCase.setUpdateBy(UserInfoUtil.getUserInfo().getUserID());tCase.setUpdateTime(DateUtils.getNowDate());//更新之前全部删除文件详细tCaseFileMapper.deleteTCaseFileById(tCase.getCaseId());List<TCaseFile> fileList = tCase.getFileList();fileList.forEach(t->{t.setCaseId(tCase.getCaseId());t.setFileId(UUID.randomUUID().toString());t.setCreateBy(UserInfoUtil.getUserInfo().getUserID());t.setCreateTime(DateUtils.getNowDate());tCaseFileMapper.insertTCaseFile(t);});return tCaseMapper.updateTCase(tCase);}

基本上就是这么多步骤

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_12184.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机毕业设计之java+javaweb的网上电子书店-图书商城网站

计算机毕业设计之javajavaweb的网上电子书店-图书商城网站 项目介绍 系统权限按管理员和用户这两类涉及用户划分。 (a) 管理员&#xff1a;管理员使用本系统涉到的功能主要有主页、个人中心、用户管理、一级分类管理、二级分类管理、电子书管理、下单购买管理、我的书籍管理、留…

MUR1100-ASEMI快恢复二极管MUR1100

编辑-Z MUR1100在DO-41封装里采用的1个芯片&#xff0c;其尺寸都是50MIL&#xff0c;是一款快恢复二极管。MUR1100的浪涌电流Ifsm为35A&#xff0c;漏电流(Ir)为10uA&#xff0c;其工作时耐温度范围为-55~150摄氏度。MUR1100采用GPP硅芯片材质&#xff0c;里面有1颗芯片组成。…

如何用Vue + Mint UI实现上拉加载更多?

引言: 上拉加载更多在移动端不论是在 app 里面还是在页面中都是必不可少的&#xff0c;以下是 mint-ui 中上拉加载更多的总结。 一、在项目中使用 mint-ui 需要先安装 查看官网 (1)安装:npm i mint-ui --save (2)在 vue 中 main.js 引入 import MintUi from mint-ui import mi…

图扑数字孪生军事营区,实现主动防御

前言 20 世纪 50 年代初中国人民解放军开始自建营区。传统营区管理系统以独立的“点状”系统为主&#xff0c;缺乏集控平台&#xff0c;全局管理复杂度高。70 年代末提出建设智能化营区&#xff0c;并向“数字化、智能化、网络化、互动化、融合化”的方向靠拢。通过建设集光电…

【车辆配送】基于模拟退火 (SA)求解车辆配送 (VPR) (Matlab代码实现)

目录 1 车辆配送问题 2 模拟退火法 3 Matlab代码实现 4 实现结果 5 参考文献 6 写在最后 1 车辆配送问题 式(9)~( 12)中, 为配送车辆到达需求点i的时间;为需求点i到需求点j的运输成本;、分别为配送车辆提前到达需求点i的或者滞后到达需求点i的单位时间内的等待成本以及惩…

C语言编译过程——预处理、编译汇编和链接详解

引言 C语言经典的 “hello world ” 程序&#xff0c;伴随着每个程序员一起步入编程世界的大门。从编写、编译到运行&#xff0c;看到屏幕上输出的“hello world ”&#xff0c;那么你知道它都经历了什么吗&#xff1f;今天我们就来聊聊这个话题。 一、从hello.c聊起 hello …

Java多线程~线程的状态以及状态转移的条件

目录 线程的六种状态 状态转移的条件 NEW RUNNABLE BLOCKED WAITING TIMED_WAITING TERMINATED 线程的六种状态 线程共有六种状态&#xff0c;分别为&#xff1a; NEW(初始状态)&#xff1a;new表示新建一个线程对象&#xff0c;即安排了工作&#xff0c;但未开始行…

Ubuntu指令说明

1、ls ls命令是list的缩写&#xff0c;用来打印出当前目录的清单。如果ls指定其他目录&#xff0c;那么就会显示指定目录里的文件及文件夹清单。通过ls命令不仅可以查看linux文件夹包含的文件&#xff0c;而且可以查看文件权限&#xff08;包括目录、文件夹、文件权限&#xf…

【逻辑】【java基础】代码逻辑思路 层级关系 【层级注解】【架构逻辑】

命名规范: 层级逻辑关系图: 层级逻辑思路图:(代码架构逻辑)

(附源码)springboot高校宿舍交电费系统 毕业设计 031552

Springboot高校宿舍交电费系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运…

低通滤波,高通滤波,中值滤波

低通滤波和高通滤波 【参考:图像处理之高通滤波及低通滤波】 低通滤波和高通滤波需用到傅里叶变换知识,可参考这里。 图像在频域里面,频率低的地方说明它是比较平滑的,因为平滑的地方灰度值变化比较小,而频率高的地方通常是边缘或者噪声,因为这些地方往往是灰度值突变的。…

用户终身价值利用xgboost进行LTV预测

在对用户进行细分的时候需要衡量用户的一个重要指标就是用户生命周期价值。不管是什么投入最终的目的是为了盈利,当然如何识别正确的用户周期价值就至关重要了。 其中用户的终身价值计算就非常容易。可以通过一个时间窗口期,即具体的时间可以是年,可以是月,也可以是日计算…

数字藏品app开发

目前大平台的数字藏品主要功能分为三个大体的方向&#xff1a; 1.建立独立的电商平台&#xff0c;平台方组织发行并销售或者赠送&#xff0c;这种玩的方式是国内的主流运行方向&#xff1b; 2.用户将持有的数字藏品引入到了社交平台&#xff0c;国外平台允许用户验证所…

React教程之每个开发人员都应该使用的可扩展和可维护的 React 项目结构

一个好的项目结构可以对项目在理解代码库、灵活性和维护方面的成功程度产生巨大影响。没有良好结构和维护的项目很快就会变成一团糟和可怕的遗产,没有人愿意与之合作。 现在,我将向您展示我在项目中经常使用的结构,并解释其背后的原因。这种结构应该是大型应用程序的一个很…

endpoint is blank

报错图 问题:简单来说使用nacos作为注册中心的时候 并没有对注册中心进行配置而出现的报错 nacos注册中心采用bootstrap.yml或者bootstrap.properties文件进行配置,所以有的人在application.yml或application.properties进行配置了 还是会报同样的错误 nacos正确的配置应该使…

使用RestfulTool插件模拟前端向后端发送请求体,通过SpringMVC结合MyBaits响应返回体

✨✨博主简介:一个会bbox的&#x1f468;‍&#x1f4bb; ✨✨个人主页:沫洺的主页 &#x1f4da;&#x1f4da;系列专栏: &#x1f4d6; JavaWeb专栏&#x1f4d6; JavaSE专栏 &#x1f4d6; Java基础专栏&#x1f4d6;vue3专栏 &#x1f496;&#x1f496;如果文章对你有所帮…

Nacos2.0.3 单例模式mysql配置启动,完整版

一、copy配置文件application.properties 从运行的容器中把application.properties文件copy到虚拟机指定目录&#xff1a;/opt/nacos/conf/ docker cp nacos:/home/nacos/conf/application.properties /opt/nacos/conf/application.properties二、修改配置文件 application.…

外汇天眼:美联储如预期再次加息75个基点 并誓言进一步加息以对抗通胀

当地时间周三下午&#xff0c;美联储(Federal Reserve)将基准利率再上调75个基点&#xff0c;并暗示将继续在远高于当前水平的水平上加息。为了降低接近上世纪80年代初以来最高水平的通货膨胀率&#xff0c;美联储将联邦基金利率上调至3%-3.25%的区间&#xff0c;为2008年初以来…

计算机专业毕业设计怎么选?计算机本科毕业设计选题 2023年选题推荐

计算机专业毕业设计怎么选?计算机本科毕业设计选题 2023年选题推荐前言 现在已经迎来2023年的毕业季,很多同学咨询“IT跃迁谷毕设展”关于计算机毕业设计选题方面的问题。例如计算机毕设选题什么好?计算机毕设选题选什么新颖一些?计算机毕设选题如何好过关一些?等等一些问…

Fabric.js 喷雾笔刷 从入门到放肆

theme: smartblue 我报名参加金石计划1期挑战——瓜分10万奖池&#xff0c;这是我的第18篇文章&#xff0c;点击查看活动详情 本文简介 点赞 关注 收藏 学会了 喷雾笔刷 SprayBrush 是 fabric.js 提供的一个很好玩的工具&#xff0c;而且 fabric.js 也封装好了很多非常方便的…