实现的功能:
1、表单数据提交,
2、表单中携带文件附件。
3、附件上传过程中进度提示。
前端使用:vue + elementui + axios
后端使用:springboot

介绍之前,先学习2个小技巧设置
1、全局loading弹框定义使用
创建一个loading.js文件:

 import {Loading} from 'element-ui'const loading = function(text) {return Loading.service({lock: true,text: text,spinner: 'el-icon-loading',background: 'rgba(0, 0, 0, 0.7)'});};export default loading;

在vue的script里面导入:

import loading from '../loading';

显示loading const _loading = loading(作品附件上传中,请稍后...) 关闭loading
_loading.close(); // 关闭加载框 更新文字
_loading.setText(‘作品上传中,进度:’ + this.progressPercent + “%”) //更新dialog进度,优化体验

2、legend线条的颜色设置
legend需要在fieldset里面,所以设置fieldset就可以。设置颜色和边框圆角

  fieldset { border:2px solid #DCDFE6;  text-align:left; border-radius: 8px;}

下面介绍2种上传文件附件的方法:
1、vue + elementui + axios上传文件的第一种方式
通过选择文件触发对应的钩子回调函数,在回调中给全局的file赋值(特别注意raw),提交的时候使用这个File类型文件。
SpringBoot的接口写法

 @Transactional@ApiOperation(notes = "报名参加接口", value = "报名参加接口", httpMethod = "POST")@PostMapping(value = "/apply",produces = "application/json;charset=UTF-8")public Result apply(RegistrationInfo registrationInfo, @RequestParam(value = "files")MultipartFile files){//同时接收RegistrationInfo这个bean参数和参数名为files的MultipartFile类型参数。//我们使用DataForm,格式提交就可以。...}
vue的代码
 <el-form-item  label="作品上传:" prop="files" size = 'small' ><el-uploadref="upload_attach"class="upload-demo"action="/user/apply" multipleaccept=".zip,.rar,.7z":limit="1":on-change="changFile":on-exceed="handleExceed":file-list="fileList":auto-upload="false"><el-button slot="trigger" size="small" type="primary">选取文件</el-button><div slot="tip" class="el-upload__tip">注:上传的文件须是压缩文件格式,且不超过50M</div></el-upload></el-form-item>

备注:**:on-change=“changFile”,在选取文件后,通过在changFile回调中给全局变量files赋值。**实际测试只有这个方法回调成功

methods中定义的方法

 changFile(file, fileList) {console.log(fileList);//选择文件后,给fileList对象赋值this.fileList = fileList},
提交上传:
     apply(){let data = new FormData();// todo 非常重要,一定要加file.raw,从浏览器中查看需要使用binary类型,后台才能正确接收this.form.files = this.fileList[0].rawconsole.log(this.fileList[0].raw)// 将form表单中的值都赋值给FormData传递给后台for(let key in this.form){console.log(this.form[key])data.append(key,this.form[key])}this.$axios.post('/user/apply',data,{headers: {'Content-Type': 'multipart/form-data'}})// 第一种,直就传个json数据,不需要设置headers// .post('/user/apply',this.form)// 第三种,可以直接传递这个form(推荐).then(resp => {console.log('请求本地接口OK')console.log(resp)if(resp.data.code == -1){// 接口返回-1,就是注册失败,提示消息提示用户this.$message({message: resp.data.msg,type: 'error'});} else if(resp.data.code == 0){console.log(resp.data)//注册成功this.$message({message: "报名成功",type: 'success'});// 跳转到登录页面// this.$router.push('/login')}}).catch(function (error) { // 请求失败处理console.log('请求本地接口失败' + error);});},
测试功能OK

特别需要注意:这样才能取到文件对象
this.form.files = this.fileList[0].raw

2、vue + elementui + springboot 上传文件的第二种方式
通过调用el-upload的submit方法,触发自定义函数,拿到param里面的File参数。

this.form.files = param.file // 将form中的files字段赋值File对象
实现的功能:
  • 表单校验
  • 添加删除附件时,附件规则校验,及时提醒用户
  • 报名时,使用loading提示用户
  • loading中显示上传的百分比

前端完整的代码:

<template><div class='myelement' v-show = body_show><p>报名页面</p><el-form ref="form" :model="form" label-width="130px" :rules="rules" ><fieldset style="width:40%;" ><legend >个人信息</legend><!-- 姓名 --><el-form-item label="姓名:" prop="apply_person_name" size = 'small' ><el-input v-model="form.apply_person_name" placeholder="请输入姓名"  class="input_width"></el-input></el-form-item></fieldset><br><fieldset style="width:40%;"><legend>报名信息</legend><el-form-item label="学校/公司/组织:" prop="apply_company" size = 'small' ><el-input v-model="form.apply_company" placeholder="请输入公司名"  class="input_width" ></el-input></el-form-item><el-form-item label="专业/部门:" prop="apply_department" size = 'small' ><el-input v-model="form.apply_department" placeholder="请输入部门"  class="input_width"></el-input></el-form-item><el-form-item label="报名赛区:" prop="apply_area" size = 'small'><el-radio v-model="form.apply_area" label="集团内部赛区">集团内部赛区</el-radio><el-radio v-model="form.apply_area" label="社会开放赛区">社会开放赛区</el-radio></el-form-item><el-form-item label="作品方向:" prop="competition_product_target" size = 'small'><el-radio v-model="form.competition_product_target" label="精益生产">精益生产</el-radio><el-radio v-model="form.competition_product_target" label="智慧服务">智慧服务</el-radio><el-radio v-model="form.competition_product_target" label="创新应用">创新应用</el-radio></el-form-item><el-form-item label="团队名称:" prop="team_name" size = 'small' ><el-input v-model="form.team_name" placeholder="请输入团队名称"  class="input_width"></el-input></el-form-item></fieldset><br><fieldset style="width:40%;"><legend>团队负责人</legend><el-form-item label="姓名:" prop="team_leader_name" size = 'small' ><el-input v-model="form.team_leader_name" placeholder="请输入队长姓名"  class="input_width" ></el-input></el-form-item><el-form-item label="岗位:" prop="team_leader_job" size = 'small' ><el-input v-model="form.team_leader_job" placeholder="请输入队长岗位"  class="input_width"></el-input></el-form-item><el-form-item label="微信号:" prop="team_leader_wechat" size = 'small'><el-input v-model="form.team_leader_wechat" placeholder="请输入队长微信号"  class="input_width"></el-input></el-form-item><el-form-item label="手机号码:" prop="team_leader_phone" size = 'small'><el-input v-model="form.team_leader_phone" placeholder="请输入队长手机号"  maxlength="11" show-word-limit class="input_width"></el-input></el-form-item><el-form-item label="邮箱:" prop="team_leader_email" size = 'small' ><el-input v-model="form.team_leader_email" placeholder="请输入队长邮箱"  class="input_width"></el-input></el-form-item><el-form-item label="身份证号码:" prop="team_leader_id_number" size = 'small'  ><el-input v-model="form.team_leader_id_number" placeholder="请输入队长身份证号码" maxlength="18" show-word-limit class="input_width"></el-input></el-form-item></fieldset><br><fieldset style="width:40%;"><legend>作品提交</legend><el-form-item label="参赛作品名称:" prop="competition_product_name" size = 'small' ><el-input v-model="form.competition_product_name" placeholder="请输入参赛作品名称"  class="input_width" ></el-input></el-form-item><el-form-item label="参赛作品简介:" prop="competition_product_introduce" size = 'small' ><el-input type = "textarea" v-model="form.competition_product_introduce" placeholder="参赛作品简介(500字内)"maxlength="500" show-word-limit class="input_width" :rows="5" ></el-input></el-form-item><el-form-item ref="upload_attach_item"  label="作品上传:" prop="files" size = 'small' ><el-uploadref="upload_attach"class="upload-demo"action="/user/apply"multipleaccept=".zip,.rar,.7z":limit="1":on-change="changFile":on-exceed="handleExceed":on-remove="removeFile":file-list="fileList":auto-upload="false":http-request="uploadSectionFile"><el-button slot="trigger" size="small" type="primary">选取文件</el-button><div slot="tip" class="el-upload__tip">注:上传的文件须是压缩文件格式,且不超过50M</div></el-upload><el-progress :percentage="progressPercent" v-show="show_progress"></el-progress></el-form-item><el-form-item label="附件名称:" prop="competition_product_attach_name" size = 'small' ><el-input v-model="form.competition_product_attach_name" placeholder="请填写附件名称"  class="input_width" ></el-input></el-form-item></fieldset><br><br><div style="text-align:left"><el-button type="primary" v-on:click="onSubmit('form')">报名</el-button></div></el-form></div>
</template><script>import loading from '../loading';export default {name: 'Apply',data () {//验证密码var validateAttach = (rule, value, callback) => {console.log(this.fileList.length)if (this.fileList.length == 0) {callback(new Error('请选择附件'));} else {callback();}};return {body_show : true,form: {apply_person_name: '',apply_company: '',apply_department: '',apply_area: '集团内部赛区',competition_product_target: '精益生产',team_name: '',team_leader_name: '',team_leader_job: '',team_leader_wechat: '',team_leader_phone: '',team_leader_email: '',team_leader_id_number: '',competition_product_name: '',competition_product_introduce: '',files:null,competition_product_attach_name: '',},fileList:[],progressPercent:0,show_progress:false,rules: {apply_person_name: [{ required: true, message: '请输入姓名', trigger: 'blur' },],apply_company: [{ required: true, message: '请输入学校/公司/组织', trigger: 'blur' },],apply_department: [{ required: true, message: '请输入专业/部门', trigger: 'blur' },],apply_area: [],competition_product_target: [],team_name: [{ required: true, message: '请输入团队名称', trigger: 'blur' },],team_leader_name: [{ required: true, message: '请输入队长姓名', trigger: 'blur' },],team_leader_job: [{ required: true, message: '请输入队长岗位', trigger: 'blur' },],team_leader_wechat: [{ required: true, message: '请输入队长微信号', trigger: 'blur' },],team_leader_phone: [{ required: true, message: '请输入队长手机号', trigger: 'blur' },{ min: 11, max: 11, message: '输入11位数字', trigger: 'blur' },],team_leader_email: [{ required: true, message: '请输入队长邮箱', trigger: 'blur' },],team_leader_id_number: [{ required: true, message: '请输入队长身份证号码', trigger: 'blur' },{ min: 18, max: 18, message: '输入18位身份证号', trigger: 'blur' },],competition_product_name: [{ required: true, message: '请输入参赛作品名称', trigger: 'blur' },],competition_product_introduce: [{ required: true, message: '请输入参赛作品简介', trigger: 'blur' },],files: [// { required: true, message: '请输入选择参赛作品', trigger: 'blur' },{ validator: validateAttach }],competition_product_attach_name: [{ required: true, message: '请输入附件名称', trigger: 'blur' },],},}},methods: {changFile(file, fileList) {console.log("changFile");console.log(fileList);//选择文件后,给fileList对象赋值this.fileList = fileListthis.$refs.upload_attach_item.validate();},removeFile(file, fileList){this.fileList = fileListthis.$refs.upload_attach_item.validate();},handleExceed(files, fileList) {this.$message.warning(`当前限制最多选择 1 个文件`);},onSubmit(formName) {// 校验合法性this.$refs[formName].validate((valid) => {if (valid) {// alert('发送post请求!');console.log('submit!')console.log(this.form)this.$refs.upload_attach.submit() // 触发调用uploadSectionFile,拿到param参数里面的File} else {console.log('error submit!!');this.$message({message: '请填写完整信息再后提交',type: 'error'});return false;}});// this.apply();// this.$refs.upload_attach.submit() // 触发调用uploadSectionFile,拿到param参数里面的File},uploadSectionFile(param) {console.log(param)let data = new FormData();// todo 非常重要,一定要加file.raw,从浏览器中查看需要使用binary类型,后台才能正确接收// this.form.files = this.fileList[0].raw// console.log(this.fileList[0].raw)this.form.files = param.file // 将form中的files字段赋值File对象console.log(param.file)// 将form表单中的值都赋值给FormData传递给后台for(let key in this.form){data.append(key,this.form[key])}const _loading = loading(`作品附件上传中,请稍后...`)// this.show_progress = trueconst config = {onUploadProgress: progressEvent => {// progressEvent.loaded:已上传文件大小// progressEvent.total:被上传文件的总大小this.progressPercent = Number((progressEvent.loaded / progressEvent.total * 100).toFixed(0))_loading.setText('作品上传中,进度:' + this.progressPercent + "%") //更新dialog进度,优化体验console.log(this.progressPercent)},headers: {'Content-Type': 'multipart/form-data'}}this.$axios.post(param.action,data,config).then(resp => {console.log('请求本地接口OK')console.log(resp)this.fileList = [];// 提交完成清空附件列表_loading.close(); // 关闭加载框// this.show_progress = falsethis.progressPercent = 0if(resp.data.code == -1){// 接口返回-1,就是报名失败,提示消息提示用户this.$message({message: resp.data.msg,type: 'error'});} else if(resp.data.code == 0){console.log(resp.data)//报名成功this.$message({message: "报名成功",type: 'success'});// 跳转到主页面// this.$router.replace('/home')}}).catch(function (error) { // 请求失败处理console.log('请求本地接口失败' + error);});},validateAttach (rule, value, callback) {console.log(value)console.log(this.$refs.upload_attach)},},created () {},}
</script><style scoped>.myelement {text-align:left}.input_width{width: 50%;width: 300px;}fieldset {border:2px solid #DCDFE6;  text-align:left; border-radius: 8px;}
</style>

后端接口

@Autowiredprivate UserService userService;@Transactional@ApiOperation(notes = "报名参加接口", value = "报名参加接口", httpMethod = "POST")@PostMapping(value = "/apply",produces = "application/json;charset=UTF-8")public Result apply(@ApiParam(name = "registrationInfo", required = true, value = "registrationInfo") RegistrationInfo registrationInfo,@RequestParam(value = "files")MultipartFile files){System.out.println("registrationInfo = " + registrationInfo.toString());HashMap<Object,Object> map = new HashMap();//将用户插入数据库中userService.addRegistrationInfo(registrationInfo);//上传附件String attachName = registrationInfo.getCompetition_product_attach_name();Map<String, Object> uploadResultMap = userService.uploadAttachFile(files, attachFileNameMap.getId());boolean success = (boolean) uploadResultMap.get("success");if(!success){map.put("result","附件上传失败");return ResultUtil.error(uploadResultMap.toString(), ReturnCode.CODE_FAIL,"附件上传失败" );}map.put("result","报名成功");return ResultUtil.success(map.toString(), ReturnCode.CODE_SUCCESS,"success");}

上传代码实现:

@Overridepublic Map<String, Object> uploadAttachFile(MultipartFile file,String uploadAttachName) {HashMap<String, Object> map = new HashMap<>();String dirName = "";String filePath = attachFileUploadPath;List<String> accTypes = Arrays.asList(".rar", ".zip");try {String fileName = file.getOriginalFilename();String suffixName = fileName.substring(fileName.lastIndexOf("."));/** 校验文件合法性 */if (accTypes.contains(suffixName)) {System.out.println(suffixName + "后缀合法");} else {System.out.println(suffixName + "后缀不合法");map.put("success", false);map.put("message", "上传文件类型有误");return map;}// TODO: 2020/6/20 这里分割符不同系统可能不一样suffixName = ".zip";String attachName = uploadAttachName;if(StringUtils.isEmpty(uploadAttachName)){//用户上传了附件名称,使用用户名称命名attachName = fileName.substring(fileName.lastIndexOf("\\")+1);attachName = attachName.split("\\.")[0] + suffixName;//使用统一后缀名}System.out.println("attachName = " + attachName + " || suffixName = " + suffixName);// TODO: 2020/6/20 需要使用唯一的标记符来命名附件名称 日期 or teamName ?System.out.println("附件路径 = " + filePath);File folder = new File(filePath);if(!folder.exists()){folder.mkdirs();}File f = new File(filePath + attachName);File fileParent = f.getParentFile();if (!fileParent.exists()) {fileParent.mkdirs();}file.transferTo(f);map.put("success", true);map.put("message", "success to upload");System.out.println("附件上传成功");} catch (Exception e) {e.printStackTrace();String msg = e.getCause().toString();map.put("success", false);map.put("message", msg);}return map;}

vue + elementui + axios表单数据和文件上传相关推荐

  1. ajax-FormData快速序列化表单数据以及文件上传

    serialize和 FormData 区别 $("form").serialize()和 new FormData($('#uploadForm')[0])都是序列化表单,实现表 ...

  2. Spring Boot + Vue 前后端分离,两种文件上传方式总结

    在Vue.js 中,如果网络请求使用 axios ,并且使用了 ElementUI 库,那么一般来说,文件上传有两种不同的实现方案: 通过 Ajax 实现文件上传 通过 ElementUI 里边的 U ...

  3. 基于ruoyi+vue+elementUI实现列表,新增,附件上传,tab+springBoot+mybatis+oracle序列+批量新增

    基于ruoyi+vue+elementUI实现列表,新增,附件上传,tab+springBoot+mybatis+oracle序列+批量新增 页面效果 列表页面 新增页面 详情页面 代码实现 列表+新 ...

  4. .vue文件_Spring Boot + Vue 前后端分离,两种文件上传方式总结!

    在Vue.js 中,如果网络请求使用 axios ,并且使用了 ElementUI 库,那么一般来说,文件上传有两种不同的实现方案: 通过 Ajax 实现文件上传 通过 ElementUI 里边的 U ...

  5. ajax post form上传图片,ajax怎样提交form表单与实现文件上传

    这次给大家带来ajax怎样提交form表单与实现文件上传,ajax提交form表单与实现文件上传的注意事项有哪些,下面就是实战案例,一起来看一下. 前几天,发现了一些小问题.我在写后台管理页面时,需要 ...

  6. Vue项目使用js-audio-recorder录音及录音文件上传

    最近在做的Vue项目里有关于录音和录音文件上传的功能,用到的是一个开源框架js-audio-recorder,官方文档上关于录音.暂停录音等也封装了很多方法,在这里我主要说下录音文件上传部分,网上找了 ...

  7. WebApi发送HTML表单数据:文件上传与多部分MIME

    5.3 Sending HTML Form Data 5.3 发送HTML表单数据(2) 本文引自:http://www.cnblogs.com/r01cn/archive/2012/12/20/28 ...

  8. (27) java web的struts2框架的使用-基于表单的多文件上传

    和单个文件上传配置都是一样的,只是在action中接受参数时候,接受的是数组,不再是单个的文件. 一,action的实现: public class MutableFilesUpload extend ...

  9. Web后端学习笔记 Flask(8) WTForms 表单验证,文件上传

    Flask-WTF是简化了WTForms操作的一个第三方库.WTForms表单的两个主要功能是验证用户提交数据的合法性以及渲染模板.同时还包含一些其他的功能.例如CSRF保护,文件上传等功能,安装fl ...

最新文章

  1. Material Design学习之 Snackbars(详细分析,Toast的加强版)
  2. JavaFX动画工具
  3. python能做人机界面吗_人机交互程序 python实现人机对话
  4. mysql中使用日期加减时无法识别年-月格式数据的问题,%Y-%m这种格式数据
  5. 【原创】大叔问题定位分享(4)Kafka集群broker节点从zookeeper上消失
  6. flash 转 html5 工具_转
  7. 关于PC浏览器js提示兼容问题的代码 “您的浏览器版本太低了,已经和时代脱轨了“ 强制锁定极速模式
  8. MyBatis递归查询
  9. pandas用法-全网最详细教程
  10. 如何设计出一款好的软件
  11. 跟这台计算机连接的一个USB设备运行不正常,Windows无法识别
  12. 跨境卖家:如何让海外KOL营销达到理想效果?
  13. TCP/IP协议 之IPV4与IPV6的区别
  14. linux usb外接硬盘,在Linux系统上使用外置USB硬盘
  15. 走进VOT--《High Performance Visual Tracking with Siamese Region Proposal Network》阅读翻译
  16. OSI模型 四层发现-nmap(诸神之眼)工具介绍
  17. iQOONeo6SE和iQOONeo5SE区别 哪个好 iQOONeo6SE和iQOONeo5SE哪个值得买 两者配置对比
  18. 时间都去哪儿了?互联网3.0时代,好多东西都已“碎片化”
  19. ChinaSoft 论坛巡礼 | 泛在计算时代的智能化运维
  20. 微信小程序使用全套指南

热门文章

  1. 网络爬虫2:使用crawler4j爬取网络内容
  2. signature=880b64448b3d486b365e09df6abfc4cc,Structural basis of βTrCP1-associated GLI3 processing
  3. 如何选择做网站的公司
  4. Android 绘图和shape圆形
  5. 汽车导航的android 系统设计,基于Android的Telematics导航系统的设计与实现
  6. 苏格拉底与柏拉图麦穗的故事
  7. MM模块库存管理常用表
  8. DeFi崛起:总锁仓量(TVL)不断飙升
  9. js面试--ajax与性能优化
  10. 【地产大数据案例】中指讯博:城市地图与投资决策