使用Vue+Spring Boot实现Excel上传功能
1.使用vue-cli创建前端项目
运用vue-cli工具可以很轻松地构建前端项目,当然,使用webstorm来构建会更加简洁(如图)。本文推荐使用webstorm,因为在后续开发中,ide会使我们的开发更加简洁。部分配置如图:
2.navbar编写
作为一个webapp,navbar作为应用的导航栏是必不可少的。在本项目中,笔者引入了bootstrap对navbar进行了轻松地构建。在vue中我们需要在components文件夹中将我们的组件加进去,对于本工程来说,navbar是我们要加入的第一个组件,他独立于router之外,一直固定在网页上方。
2.1 首先,我们使用npm来安装vue,vue-cli,bootstrap
npm install vue npm install -g vue-cli npm install --save bootstrap jquery popper.js
2.2 接下来我们在components目录下new一个vue组件,并且在main.js中引入bootstrap依赖:
import 'bootstrap/dist/css/bootstrap.min.css' import 'bootstrap/dist/js/bootstrap.min'
2.3 下面就可以开始写代码了,由于本文只关注table相关的功能,所以导航栏中除了script意外的元素都已经disable,代码如下:
<template> <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <span class="navbar-brand mb-0 h1">vue-springboot</span> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarnav" aria-controls="navbarnav" aria-expanded="false" aria-label="toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarnav"> <ul class="navbar-nav"> <li class="nav-item"> <router-link class="nav-link" to="/home">home</router-link> </li> <li class="nav-item active"> <router-link to="/" class="nav-link">script</router-link> </li> <li class="nav-item"> <router-link to="/history" class="nav-link">history</router-link> </li> </ul> </div> </nav> </template> <script> export default { name: "mynavbar" } </script> <style scoped> </style>
2.3 在app.vue中引入mynavbar
3.script table编写
作为自动化工具,必不可少的一部分就是引入script,我们希望用户能够*地使用h5界面进行script的编写,因此在这里使用了vue的数据双向绑定进行table crud。
3.1 新建一个vue组件scripttable,代码如下:
<template> <div class="container-fluid" id="scripttable"> <h3>my script</h3> <form style="margin-top: 1rem"> <input type="file" @change="getfile($event)" class="" multiple/> <input type="button" value="upload" @click="submit($event)" class="btn btn-dark"> </form> <table class="table table-hover text-center table-bordered" style="word-break: break-all; word-wrap: break-word;margin-top: 1rem;"> <thead> <th>#</th> <th>platform</th> <th>action</th> <th>path</th> <th>value</th> <th>wait</th> <th>screenshot</th> <th>change</th> </thead> <tbody> <tr v-cloak v-for="(item, index) in steps"> <th>{{index+1}}</th> <td>{{item.platform}}</td> <td>{{item.action}}</td> <td>{{item.path}}</td> <td>{{item.value}}</td> <td>{{item.wait}}</td> <td>{{item.screenshot}}</td> <td><a href="#" v-on:click="edit(item)">edit</a> | <a href="#" v-on:click='aaa(index)'>delete</a> </td> </tr> <tr> <th></th> <td><select class="form-control" v-model="stepstemp.platform"> <option>web</option> <option>android</option> </select></td> <td><select class="form-control" v-model="stepstemp.action"> <option>click</option> <option>get</option> <option>input</option> <option>swipe</option> </select></td> <td><input class="form-control" v-model="stepstemp.path" placeholder="enter the xpath"></td> <td><input class="form-control" v-model="stepstemp.value" placeholder="enter the input value"></td> <td><input class="form-control" v-model="stepstemp.wait" placeholder="waiting seconds"></td> <td><select class="form-control" v-model="stepstemp.screenshot"> <option>yes</option> <option>no</option> </select></td> <td> <button class="btn btn-sm btn-dark" v-on:click='save' v-if="isnotedit">save</button> <button class="btn btn-sm btn-primary" v-on:click='saveedit' v-else>saveedit</button> </td> </tr> </tbody> </table> <hr/> </div> </template> <script> import vue from 'vue' import axios from 'axios' export default { name: "scripttable", data() { return ({ steps: [], stepstemp: { platform: '', action: '', path: '', value: '', wait: '', screenshot: '' }, isnotedit: true }); }, methods: { save: function () { this.steps.push(this.stepstemp); this.stepstemp = { platform: '', action: '', path: '', value: '', wait: '', screenshot: '' }; }, aaa: function (index) { this.steps.splice(index, 1) }, edit: function (item) { this.isnotedit = false; this.stepstemp = item; }, saveedit: function () { this.isnotedit = true; this.stepstemp = { platform: '', action: '', path: '', value: '', wait: '', screenshot: '' }; } } } </script> <style scoped> </style>
3.3 运行dev,打开localhost:8080
npm run dev
前端页面效果如下:
至此,本文相关的纯前端部分完成地差不多了,加上mock的数据后,我们可以开始进行后端的开发了。
4.使用spring initializr创建后端项目
为了更轻松地构建工程,构建restful api以及更轻松地配置请求处理,笔者选择了spring boot作为后端框架。
4.1 首先我们使用idea集成的spring initializr来构建项目,部分配置如图:
4.2 接下来在pom.xml中引入poi依赖,点击import change。如下所示:
<dependency> <groupid>org.apache.poi</groupid> <artifactid>poi-ooxml</artifactid> <version>4.0.0</version> </dependency>
4.3 接下来我们在application.properties中配置server.port=8088,与前端项目分开
5.pojo类step的编写
下面是对pojo类的编写,本文所需的pojo只有step一种,与前端的table相对应,代码如下:
import lombok.data; @data public class step { private string platform; private string action; private string path; private string value; private int wait; private string screenshot; }
6.uploadcontroller的编写
接下来是对前端post请求的handler(controller)进行编写,我们将上传这个post请求与"/uploadfile"相对应,注意加入@crossorigin注解实现跨域,代码如下:
package com.daniel.vuespringbootuploadbe; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.controller; import org.springframework.web.bind.annotation.crossorigin; import org.springframework.web.bind.annotation.postmapping; import org.springframework.web.bind.annotation.responsebody; import org.springframework.web.multipart.multipartfile; import java.io.file; import java.io.ioexception; import java.nio.file.files; import java.nio.file.path; import java.nio.file.paths; import java.util.list; @controller @crossorigin @responsebody public class uploadcontroller { private static string uploaded_folder = "src/main/resources/static/temp/"; @autowired private loadservice loadservice; @postmapping("/upload") public list<step> singlefileupload(multipartfile file) { try { // get the file and save it somewhere byte[] bytes = file.getbytes(); path path = paths.get(uploaded_folder + file.getoriginalfilename()); files.write(path, bytes); } catch (ioexception e) { e.printstacktrace(); } // print file data to html list<step> result = loadservice.casttostep(new file(uploaded_folder + file.getoriginalfilename())); return result; } }
7.loadservice的编写
下面该编写service来读取请求中传送的文件了,简单地来说只有一个步骤,将excel中的script转换为pojo的链表并在controller中作为responsebody返回.
7.1 首先创建service接口,代码如下:
package com.daniel.vuespringbootuploadbe; import org.springframework.stereotype.service; import java.io.file; import java.util.list; @service public interface loadservice { list<step> casttostep(file file); }
7.2 接下来创建service实现类,代码如下:
package com.daniel.vuespringbootuploadbe; import org.apache.poi.openxml4j.exceptions.invalidformatexception; import org.apache.poi.ss.usermodel.row; import org.apache.poi.ss.usermodel.sheet; import org.apache.poi.ss.usermodel.workbook; import org.apache.poi.xssf.usermodel.xssfworkbook; import org.springframework.stereotype.service; import java.io.file; import java.io.ioexception; import java.util.arraylist; import java.util.list; @service public class loadserviceimpl implements loadservice { @override public list<step> casttostep(file file) { list<step> steps = new arraylist<>(); workbook workbook = null; try { workbook = new xssfworkbook(file); } catch (ioexception e) { e.printstacktrace(); } catch (invalidformatexception e) { e.printstacktrace(); } sheet sheet = workbook.getsheetat(0); int num = sheet.getlastrownum() - sheet.getfirstrownum(); //read steps for (int i = 0; i < num; i++) { row row = sheet.getrow(i+1); step step = new step(); step.setplatform(row.getcell(0).getstringcellvalue()); step.setaction(row.getcell(1).getstringcellvalue()); step.setpath(row.getcell(2).getstringcellvalue()); step.setvalue(row.getcell(3).getstringcellvalue()); step.setwait((int) row.getcell(4).getnumericcellvalue()); step.setscreenshot(row.getcell(5).getstringcellvalue()); steps.add(step); } try { workbook.close(); } catch (ioexception e) { e.printstacktrace(); } return steps; } }
8.搭建简单的restful api
文章临近尾声,现在前后端的独立代码基本开发完毕,是时候搭建restful了,本文中的api非常简单,就是对上传做出响应,并将返回的json写入界面上的table中,完成script导入,npm安装axios后,在scripttable组件中加入如下代码:
getfile: function (event) { this.file = event.target.files[0]; console.log(this.file); }, submit: function (event) { event.preventdefault(); let formdata = new formdata(); formdata.append("file", this.file); axios.post('http://localhost:8088/upload', formdata) .then(function (response) { for (let i = 0; i < response.data.length; i++) { var tempdata = { platform: response.data[i].platform, action: response.data[i].action, path: response.data[i].path, value: response.data[i].value, wait: response.data[i].wait, screenshot: response.data[i].screenshot }; this.steps.push(tempdata); } }.bind(this)) .catch(function (error) { alert("fail"); console.log(error); }); }
9.运行服务,编写script并上传
接下来我们创建一个excel,按如图格式编写简单script,运行前后端服务,实现上传:
运行后,excel文件会上传到后端工程的static的temp目录中
总结
以上所述是小编给大家介绍的使用vue+spring boot实现excel上传功能,希望对大家有所帮助
下一篇: 在DIV+CSS排版中新闻列表的制作方法