springMVC从上传的Excel文件中读取数据

╰+哭是因爲堅強的太久メ 2021-09-26 00:10 439阅读 0赞

示例:导入客户文件(Excle文件)

797348-20151129031630703-1252185249.png

一、编辑customer.xlsx

797348-20151129032010860-20154208.png

二、在spring的xml文件设置上传文件大小

  1. <!-- 上传文件拦截,设置最大上传文件大小 10M=10*1024*1024(B)=10485760 bytes -->
  2. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  3. <property name="maxUploadSize" value="10485760" />
  4. </bean>

三、编辑jsp(addCustomer3.jsp)

复制代码

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  5. <html>
  6. <%
  7. String importMsg="";
  8. if(request.getSession().getAttribute("msg")!=null){
  9. importMsg=request.getSession().getAttribute("msg").toString();
  10. }
  11. request.getSession().setAttribute("msg", "");
  12. %>
  13. <head>
  14. <title>批量导入客户</title>
  15. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  16. <body>
  17. <div><font color="bule">批量导入客户</font></div>
  18. <form action="addController/batchimport" method="post" enctype="multipart/form-data" οnsubmit="return check();">
  19. <div style="margin: 30px;"><input id="excel_file" type="file" name="filename" accept="xlsx" size="80"/>
  20. <input id="excel_button" type="submit" value="导入Excel"/></div>
  21. <font id="importMsg" color="red"><%=importMsg%></font><input type="hidden"/>
  22. </form>
  23. </body>
  24. <script type="text/javascript">
  25. function check() {
  26. var excel_file = $("#excel_file").val();
  27. if (excel_file == "" || excel_file.length == 0) {
  28. alert("请选择文件路径!");
  29. return false;
  30. } else {
  31. return true;
  32. }
  33. }
  34. $(document).ready(function () {
  35. var msg="";
  36. if($("#importMsg").text()!=null){
  37. msg=$("#importMsg").text();
  38. }
  39. if(msg!=""){
  40. alert(msg);
  41. }
  42. });
  43. </script>
  44. </html>

复制代码

四、编辑java文件

4.1 控制器代码(AddController.java)

复制代码

  1. @Controller
  2. @RequestMapping("toPage/addController/")
  3. public class AddController {
  4. private static Log log = LogFactory.getLog(AddController.class);
  5. @Autowired
  6. private CustomerService customerService;
  7. @RequestMapping(value = "batchimport", method = RequestMethod.POST)
  8. public String batchimport(@RequestParam(value="filename") MultipartFile file,
  9. HttpServletRequest request,HttpServletResponse response) throws IOException{
  10. log.info("AddController ..batchimport() start");
  11. //判断文件是否为空
  12. if(file==null) return null;
  13. //获取文件名
  14. String name=file.getOriginalFilename();
  15. //进一步判断文件是否为空(即判断其大小是否为0或其名称是否为null)
  16. long size=file.getSize();
  17. if(name==null || ("").equals(name) && size==0) return null;
  18. //批量导入。参数:文件名,文件。
  19. boolean b = customerService.batchImport(name,file);
  20. if(b){
  21. String Msg ="批量导入EXCEL成功!";
  22. request.getSession().setAttribute("msg",Msg);
  23. }else{
  24. String Msg ="批量导入EXCEL失败!";
  25. request.getSession().setAttribute("msg",Msg);
  26. }
  27. return "Customer/addCustomer3";
  28. }
  29. }

复制代码

4.2 服务层代码(CustomerService.java),即上述方法中 customerService.batchImport(name,file);语句所调用的方法

复制代码

  1. //批量导入客户
  2. public boolean batchImport(String name,MultipartFile file){
  3. boolean b = false;
  4. //创建处理EXCEL
  5. ReadExcel readExcel=new ReadExcel();
  6. //解析excel,获取客户信息集合。
  7. List<Customer> customerList = readExcel.getExcelInfo(name ,file);
  8. if(customerList != null){
  9. b = true;
  10. }
  11. //迭代添加客户信息(注:实际上这里也可以直接将customerList集合作为参数,在Mybatis的相应映射文件中使用foreach标签进行批量添加。)
  12. for(Customer customer:customerList){
  13. customerDoImpl.addCustomers(customer);
  14. }
  15. return b;
  16. }

复制代码

4.3 工具类代码(ReadExcel.java),即上述方法中readExcel.getExcelInfo(name ,file);语句所调用的方法以及其他相关的方法

Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。不过这首先得判断Excel的版本而选择不同的Workbook的方式(2003版本对应的是HSSFWorkbook,2007版本及以上对应的是XSSFWorkbook)。此外,一般来说先将在客户端用户上传的文件拷贝一份至服务器的本地磁盘中,然后再从这个拷贝文件中进行读取,这样就避免了因客户端的网络异常或其他状况而在读取时造成的数据流失或损坏的情况。

复制代码

  1. package com.jun.util;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.util.ArrayList;
  7. import java.util.Date;
  8. import java.util.List;
  9. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  10. import org.apache.poi.ss.usermodel.Cell;
  11. import org.apache.poi.ss.usermodel.Row;
  12. import org.apache.poi.ss.usermodel.Sheet;
  13. import org.apache.poi.ss.usermodel.Workbook;
  14. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Controller;
  17. import org.springframework.web.multipart.MultipartFile;
  18. import org.springframework.web.multipart.commons.CommonsMultipartFile;
  19. import com.jun.service.CustomerService;
  20. import com.jun.vo.Customer;
  21. public class ReadExcel {
  22. //总行数
  23. private int totalRows = 0;
  24. //总条数
  25. private int totalCells = 0;
  26. //错误信息接收器
  27. private String errorMsg;
  28. //构造方法
  29. public ReadExcel(){}
  30. //获取总行数
  31. public int getTotalRows() { return totalRows;}
  32. //获取总列数
  33. public int getTotalCells() { return totalCells;}
  34. //获取错误信息
  35. public String getErrorInfo() { return errorMsg; }
  36. /**
  37. * 验证EXCEL文件
  38. * @param filePath
  39. * @return
  40. */
  41. public boolean validateExcel(String filePath){
  42. if (filePath == null || !(WDWUtil.isExcel2003(filePath) || WDWUtil.isExcel2007(filePath))){
  43. errorMsg = "文件名不是excel格式";
  44. return false;
  45. }
  46. return true;
  47. }
  48. /**
  49. * 读EXCEL文件,获取客户信息集合
  50. * @param fielName
  51. * @return
  52. */
  53. public List<Customer> getExcelInfo(String fileName,MultipartFile Mfile){
  54. //把spring文件上传的MultipartFile转换成CommonsMultipartFile类型
  55. CommonsMultipartFile cf= (CommonsMultipartFile)Mfile; //获取本地存储路径
  56. File file = new File("D:\\fileupload");
  57. //创建一个目录 (它的路径名由当前 File 对象指定,包括任一必须的父路径。)
  58. if (!file.exists()) file.mkdirs();
  59. //新建一个文件
  60. File file1 = new File("D:\\fileupload" + new Date().getTime() + ".xlsx");
  61. //将上传的文件写入新建的文件中
  62. try {
  63. cf.getFileItem().write(file1);
  64. } catch (Exception e) {
  65. e.printStackTrace();
  66. }
  67. //初始化客户信息的集合
  68. List<Customer> customerList=new ArrayList<Customer>();
  69. //初始化输入流
  70. InputStream is = null;
  71. try{
  72. //验证文件名是否合格
  73. if(!validateExcel(fileName)){
  74. return null;
  75. }
  76. //根据文件名判断文件是2003版本还是2007版本
  77. boolean isExcel2003 = true;
  78. if(WDWUtil.isExcel2007(fileName)){
  79. isExcel2003 = false;
  80. }
  81. //根据新建的文件实例化输入流
  82. is = new FileInputStream(file1);
  83. //根据excel里面的内容读取客户信息
  84. customerList = getExcelInfo(is, isExcel2003);
  85. is.close();
  86. }catch(Exception e){
  87. e.printStackTrace();
  88. } finally{
  89. if(is !=null)
  90. {
  91. try{
  92. is.close();
  93. }catch(IOException e){
  94. is = null;
  95. e.printStackTrace();
  96. }
  97. }
  98. }
  99. return customerList;
  100. }
  101. /**
  102. * 根据excel里面的内容读取客户信息
  103. * @param is 输入流
  104. * @param isExcel2003 excel是2003还是2007版本
  105. * @return
  106. * @throws IOException
  107. */
  108. public List<Customer> getExcelInfo(InputStream is,boolean isExcel2003){
  109. List<Customer> customerList=null;
  110. try{
  111. /** 根据版本选择创建Workbook的方式 */
  112. Workbook wb = null;
  113. //当excel是2003时
  114. if(isExcel2003){
  115. wb = new HSSFWorkbook(is);
  116. }
  117. else{//当excel是2007时
  118. wb = new XSSFWorkbook(is);
  119. }
  120. //读取Excel里面客户的信息
  121. customerList=readExcelValue(wb);
  122. }
  123. catch (IOException e) {
  124. e.printStackTrace();
  125. }
  126. return customerList;
  127. }
  128. /**
  129. * 读取Excel里面客户的信息
  130. * @param wb
  131. * @return
  132. */
  133. private List<Customer> readExcelValue(Workbook wb){
  134. //得到第一个shell
  135. Sheet sheet=wb.getSheetAt(0);
  136. //得到Excel的行数
  137. this.totalRows=sheet.getPhysicalNumberOfRows();
  138. //得到Excel的列数(前提是有行数)
  139. if(totalRows>=1 && sheet.getRow(0) != null){
  140. this.totalCells=sheet.getRow(0).getPhysicalNumberOfCells();
  141. }
  142. List<Customer> customerList=new ArrayList<Customer>();
  143. Customer customer;
  144. //循环Excel行数,从第二行开始。标题不入库
  145. for(int r=1;r<totalRows;r++){
  146. Row row = sheet.getRow(r);
  147. if (row == null) continue;
  148. customer = new Customer();
  149. //循环Excel的列
  150. for(int c = 0; c <this.totalCells; c++){
  151. Cell cell = row.getCell(c);
  152. if (null != cell){
  153. if(c==0){//第一列不读
  154. }else if(c==1){
  155. customer.setcName(cell.getStringCellValue());//客户名称
  156. }else if(c==2){
  157. customer.setSimpleName(cell.getStringCellValue());//客户简称
  158. }else if(c==3){
  159. customer.setTrade(cell.getStringCellValue());//行业
  160. }else if(c==4){
  161. customer.setSource(cell.getStringCellValue());//客户来源
  162. }else if(c==5){
  163. customer.setAddress(cell.getStringCellValue());//地址
  164. }else if(c==6){
  165. customer.setRemark(cell.getStringCellValue());//备注信息
  166. }
  167. }
  168. }
  169. //添加客户
  170. customerList.add(customer);
  171. }
  172. return customerList;
  173. }
  174. }

复制代码

4.4 工具类代码(WDWUtil.java)

复制代码

  1. public class WDWUtil {
  2. // @描述:是否是2003的excel,返回true是2003
  3. public static boolean isExcel2003(String filePath) {
  4. return filePath.matches("^.+\\.(?i)(xls)$");
  5. }
  6. //@描述:是否是2007的excel,返回true是2007
  7. public static boolean isExcel2007(String filePath) {
  8. return filePath.matches("^.+\\.(?i)(xlsx)$");
  9. }
  10. }

复制代码

说明:上面的代码为了阅读便利而先贴的是父方法,后贴的是子方法,而在实际的代码编辑中一般是先编辑子方法,后编辑父方法,如上面应该是先编辑工具类的代码,再编辑服务层的代码,最后编辑控制器的代码。

运行结果:(先点击“选择文件”,再点击“导入Excel”)

797348-20151129042343828-2090442344.png

数据库:

797348-20151129042512297-875743058.png

后记:此博客省略了模型层的代码,此项目采用的是Mybatis。

鉴于博友提的上传去重的问题,也是思考了自己的想法,这里先引用其他博友解决的思路 Excel导入去重

发表评论

表情:
评论列表 (有 0 条评论,439人围观)

还没有评论,来说两句吧...

相关阅读