700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > vue + elementui + axios表单数据和文件上传

vue + elementui + axios表单数据和文件上传

时间:2024-07-27 21:47:10

相关推荐

vue + elementui + axios表单数据和文件上传

实现的功能:

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="petition_product_target" label="精益生产">精益生产</el-radio><el-radio v-model="petition_product_target" label="智慧服务">智慧服务</el-radio><el-radio v-model="petition_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="petition_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="petition_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="petition_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: /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: /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;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。