基于Java语言SpringMVC框架的Excel上传解析以及下载教程

来源:互联网 发布:雅思6.5知乎 编辑:程序博客网 时间:2024/06/05 12:48

基于SpringMVC的Excel上传解析以及下载

简介:

本文主要基于Java的,介绍的分为三个部分,文件上传、Excel解析、文件下载,然而这三个部分都有各种各样的方法实现,原生的最通用,但也是代码量最多,本文介绍的只是基于spring,可能使用的人群没原生的那么多,仅供参考。

说明:

本文所提示的依赖的jar包指的都是主要的jar,其中还需要其他的jar未具体一一说明,这个官网上下载都会有提示相关下载的,但为了方便各位道友,点击此处打开下载页面。

文件上传:

文件上窜的思路是提交一个带文件的表单,后台动过循环遍历表单元素判断是传统数据还是文件流数据,如果是文件流数据则进行文件接收保存。

依赖的jar:commons-fileupload-1.2.1.jar。

下面贴出代码以及注释,其中加粗的是核心代码,其他的是我项目中的其他代码可以忽略。

public void upExcel(HttpServletRequest request, HttpServletResponse response) throws IllegalStateException, IOException {// 定义返回值Map<String, Object> resMap = new HashMap<String, Object>();String chatid = request.getParameter("chatid");if (chatid == null || "".equals(chatid)) {resMap.put("resCode", "4");resMap.put("resMsg", "群组参数错误!");responseToPage(request, response, new JSONObject(resMap).toString());return;}// 定义服务器保存的文件名(因为我的项目特殊需求,后上传的文件覆盖前面的文件,所以采用写死的文件名,这个可以根据不同的需求生成文件名)String name = "ldry";// 检索文件CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());if(multipartResolver.isMultipart(request)) {MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;Iterator<?> iter = multiRequest.getFileNames();while(iter.hasNext()) {                // 遍历文件MultipartFile file = multiRequest.getFile(iter.next().toString());if(file != null && file.getSize() > 0) {// 获取文件后缀String postfix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);// 文件类型校验if (!"xls".equals(postfix) && !"xlsx".equals(postfix)) {resMap.put("r esCode", "3");resMap.put("resMsg", "请上传*.xls/*.xlsx类型的文件!");responseToPage(request, response, new JSONObject(resMap).toString());return;}// 获取文件目录String pathLast = this.getServletContext().getRealPath("/WEB-INF/upload");// 校验 创建文件目录File filepath = new File(pathLast);if (!filepath.exists() && !filepath.isDirectory()) {System.out.println("创建目录 " + pathLast);filepath.mkdir();}// 清空相关旧文件File delFile1 = new File(filepath + "\\"+ name + ".xls");delFile1.delete();File delFile2 = new File(filepath + "\\"+ name + ".xlsx");delFile2.delete();// 拼装完整文件路径String path = pathLast + "\\"+ name + "." + postfix;// 保存file.transferTo(new File(path));// 解析EXCELresMap = ExcelToDB(path,chatid);                } else {                resMap.put("resCode", "3");resMap.put("resMsg", "请勿导入空文件!");                }            }        } else {        resMap.put("resCode", "3");resMap.put("resMsg", "未识别文件");        }        responseToPage(request, response, new JSONObject(resMap).toString());    }

HTML代码,为了能自己定义上传文件的样式,本文是吧上传文件的空间跳成透明,在其上面防止空间实现的,仅供参考,注意

 enctype="multipart/form-data"
是设置表单拥有文件元素,这个必须加

 encoding="multipart/form-data"
是为了兼容某可恶浏览器

<div class="filegroup"><label class="upstyle btn btn-success">选择文件<form id="upFileForm" enctype="multipart/form-data" encoding="multipart/form-data"><input type="hidden" id="chatid" name="chatid" /> <input type="file" id="filexz" name="upexcel" style="border: solid;" accept=".xls,.xlsx" /> </form> </label> <label class="upTip"> 未选择文件 </label><button type="button" class="subbtn btn btn-success" onclick="subfile()">  保 存  </button></div>
css把文件元素设置成透明,其他的样式此处就不贴出来了

#filexz{width: 100px;    position: absolute;    top: 0;    opacity: 0;}
下面贴出js代码,红色部分是相关代码,其他部分可忽略
$(function() {filetip();});// 文件选择提示function filetip() {$(".upstyle").on("change",function(){    var filePath = $("#filexz").val();    if(filePath.indexOf("xls") != -1 || filePath.indexOf("xlsx") != -1){        var arr = filePath.split('\\');        var fileName = arr[arr.length-1];        $(".upTip").css("color", "green");        $(".upTip").html(fileName);    }else{        $(".upTip").css("color", "red");        $(".upTip").html("请选择*.xls/*.xlsx类型的文件!");        return false;    }});}// 文件上传(表单提交)function subfile() {var upload = window.top.layer.load(1);var form = new FormData(document.getElementById("upFileForm"));$.ajax({url : "<%=basePath%>suzhou/bg/lhzh/lhzh.do?action=upExcel",type : "post",data : form,processData : false,contentType : false,success : function(value){window.top.layer.close(upload); // 关闭正在上传提示var result = JSON.parse(value);if (result.resCode == "0") {window.top.layer.msg(result.resMsg, {icon: 1, time: 2000});location.reload();} else if (result.resCode == "1") {window.top.layer.alert(result.resMsg + ".\n其他记录已导入",{icon: 6});} else {window.top.layer.alert(result.resMsg,{icon: 5});}},error:function(e){window.top.layer.alert("请求错误!",{icon: 2});}});}

Excel解析:
要注意的是其实也可以在上传文件时解析Excel,但是个人不推荐那样,因为如果文件较大是需要一定的时间的,然而这段时间操作端要是断网或者其他原因导致上传中断会造成一系列的错误,所以推荐先把文件保存下来再解析。Excel解析其实就是读取文件然后获取Excel里面的工作表(sheet),行(row),列(cell),这个一般都可以通过遍历解决,但不同的需求可以采取不同的方式,比如我的项目只看第一张工作表的,我就不遍历工作表
sheet)只看第一张,列支取指定两列的我也不遍历,毕竟如果套三层循环,对效率影响还是很大的。

依赖的jar包:poi-3.16.jar。

下面贴出代码以及注释,其中加粗的是核心代码,其他的是我项目中的其他代码可以忽略

private Map<String, Object> ExcelToDB(String path,String chatid) {Map<String, Object> resMap = new HashMap<String, Object>();resMap.put("resCode", "0");String resMsg = "";File file = new File(path);InputStream is = null;int rowNum = 0;try {is = new FileInputStream(file);Workbook wb = null;// 获取后缀名String postfix = path.substring(path.lastIndexOf(".") + 1); if ("xls".equals(postfix)) {wb = new HSSFWorkbook(is);} else {wb = new XSSFWorkbook(is);}// 遍历工作表(此处项目需要,所以只关心第一张工作表)Sheet sheet = wb.getSheetAt(0);List<Object[]> objs = new ArrayList<Object[]>();// 总行数int totalRows = sheet.getPhysicalNumberOfRows(); // 遍历当前工作表的行for (int i = 1; i < totalRows; i++) {int type = 0; // 人员类别 0短期值班/1长期值班rowNum = i + 1;Row row = sheet.getRow(i);if (row == null) {continue;}// 遍历当前行的列,此处项目需要,不做遍历Cell c0 = row.getCell(0);Cell c1 = row.getCell(1);// 身份证号初处理if (c0 == null || "".equals(c0.toString().trim())) {resMap.put("resCode", "1");resMsg += "第" + rowNum + "行第1列为空。";continue;}c0.setCellType(CellType.STRING);String idcard = getCellValue(c0).trim();// 此处判断是否为空,可以用其他的判断,此处为了项目代码统一if (StringUtils.isEmpty(idcard)) continue;// 此处过滤掉特定的数据if ("320666666666666666".equals(idcard)) continue; // 值班时间以及人员类别处理String time = null;if (c1 == null || "".equals(c1.toString().trim())) {type = 1;} else {SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");c1.setCellType(CellType.NUMERIC);if (c1.getNumericCellValue() == 0.0) {resMap.put("resCode", "1");resMsg += "第" + rowNum + "行第2列日期格式异常。";continue;}time = sdf.format(c1.getDateCellValue());}Object[] obj = new Object[]{time,chatid,idcard,type};objs.add(obj);}int[] zbres = this.flowper_service.batchSave(objs);if ("0".equals(resMap.get("resCode"))) {resMsg = "导入成功";}resMap.put("resMsg", resMsg);try {is.close();} catch (IOException e) {is = null;e.printStackTrace();        }} catch (FileNotFoundException e) {// e.printStackTrace();resMap.put("resCode", "2");resMap.put("resMsg", "创建文件流失败!");} catch (IOException e) {// e.printStackTrace();resMap.put("resCode", "2");resMap.put("resMsg", "读取文件失败!");} finally {if(is != null) {try {is.close();} catch (IOException e) {is = null;e.printStackTrace();        }}}return resMap;}
此处为了准确解析而且解析的字段不多,所以在代码里手动转化了数据格式以及类型,下面贴出通用方法,但是由于环境不同有的不能用的可以参考上面的手动解析的

/** * 获取Excel单元格的值 * PS:奇葩的POI。把getCellType()给过时了却没推出新的获取单元格类型方法<p> *      导致代码在有些编译器上挺难看的。 */@SuppressWarnings("deprecation")public String getCellValue(Cell cell) {if (null != cell) {     switch (cell.getCellType()) {     case Cell.CELL_TYPE_NUMERIC: // 数字return cell.getNumericCellValue() + "";     case Cell.CELL_TYPE_STRING: // 字符串return cell.getStringCellValue() + "";     case Cell.CELL_TYPE_BOOLEAN: // 布尔return cell.getBooleanCellValue() + "";     case Cell.CELL_TYPE_FORMULA: // 公式return cell.getCellFormula() + "";     case Cell.CELL_TYPE_BLANK: // 空值return "";case Cell.CELL_TYPE_ERROR: // 故障return "";default:return "未知类型";}} else {return "";}}


文件下载:

文件下载就是服务端直接把文件以流的形式输出给浏览器,废话不多说,直接贴代码
HTML代码
<a href="<%=basePath%>suzhou/bg/lhzh/lhzh.do?action=downExcel"><u><I></i>点击这里</I></u></a>
Java后台代码

public void downExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {JSONObject res = new JSONObject();res.put("errcode", "0");res.put("errmsg", "下载成功");String fileName = "值班表示例.xls";// 此处对文件名进行编码一方乱码的,可视情况使用// fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8");// 文件路径String path = this.getServletContext().getRealPath("/WEB-INF/download");File file = new File(path + "\\" + fileName);if(!file.exists()){res.put("errcode", "1");res.put("errmsg", "您要下载的资源已被删除!");responseToPage(request, response, res.toString());return;}// 设置响应头,让浏览器下载文件response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));// 文件放到输入流FileInputStream in = new FileInputStream(path + "\\" + fileName);// 创建输出流OutputStream out = response.getOutputStream();// 创建缓冲区byte buffer[] = new byte[1024];int len = 0;while ((len = in.read(buffer)) > 0) {// 输出缓冲区的内容到浏览器,实现文件下载out.write(buffer, 0, len);}in.close();out.close();}
本文介绍就到此结束了,希望对您有所帮助,也感谢您的阅读和支持