首页 > 代码库 > Java上传下载excel、解析Excel、生成Excel

Java上传下载excel、解析Excel、生成Excel

在软件开发过程中难免需要批量上传与下载,生成报表保存也是常有之事,最近集团门户开发用到了Excel模版下载,Excel生成,圆满完成,对这一知识点进行整理,资源共享,有不足之处还望批评指正,文章结尾提供了所需jar包的下载,方便大伙使用,下面言归正传!

1.Excel的下载

1)Action中:

添加响应事件,通过getRealPath获得工程路径,与jsp中获得request.getContextPath()效果相同,fileName为要下载的文件名,经过拼接filePath是xls文件的绝对路径,调用工具类DownLoadUtil中的downLoadUtil方法;

 public ActionForward downLoadExcelModel(ActionMapping actionMapping,           ActionForm actionForm, HttpServletRequest request,           HttpServletResponse response) throws Exception {           String path = request.getSession().getServletContext().getRealPath(            "/resources");           String fileName = "成员模版.xls";           String filePath = path + "\\" + fileName;           DownLoadUtil.downLoadFile(filePath, response, fileName, "xls");           return null;        }

 

 

2)工具类DownLoadUtil中:

 

 public static boolean downLoadFile(String filePath,        HttpServletResponse response, String fileName, String fileType)        throws Exception {        File file = new File(filePath);  //根据文件路径获得File文件        //设置文件类型(这样设置就不止是下Excel文件了,一举多得)        if("pdf".equals(fileType)){           response.setContentType("application/pdf;charset=GBK");        }else if("xls".equals(fileType)){           response.setContentType("application/msexcel;charset=GBK");        }else if("doc".equals(fileType)){           response.setContentType("application/msword;charset=GBK");        }        //文件名        response.setHeader("Content-Disposition", "attachment;filename=\""            + new String(fileName.getBytes(), "ISO8859-1") + "\"");        response.setContentLength((int) file.length());        byte[] buffer = new byte[4096];// 缓冲区        BufferedOutputStream output = null;        BufferedInputStream input = null;        try {          output = new BufferedOutputStream(response.getOutputStream());          input = new BufferedInputStream(new FileInputStream(file));          int n = -1;          //遍历,开始下载          while ((n = input.read(buffer, 0, 4096)) > -1) {             output.write(buffer, 0, n);          }          output.flush();   //不可少          response.flushBuffer();//不可少        } catch (Exception e) {          //异常自己捕捉               } finally {           //关闭流,不可少           if (input != null)                input.close();           if (output != null)                output.close();        }       return false;    }

 

 

 

这样,就可以完成文件的下载,java程序将文件以流的形式,保存到客户本机!!

2、Excel的上传与解析(此处方面起见,ExcelN行两列,以为手机号,另一为短号)

对于数据批量上传,就涉及到文件的上传与数据的解析功能,此处运用了第三方jar包,方便快捷。对于文件上传,用到了commons-fileupload-1.1.1.jar与commons-io-1.1.jar,代码中并没有导入common-io包中的内容,而fielupload包的上传依赖于common-io,所以两者皆不可少;而对于Excel的解析,此处用到了jxl-2.6.jar。下面通过代码对各步骤进行解析。

1)jsp文件:

对于文件的上传,强烈推荐使用form表单,并设置enctype="multipart/form-data" method="post",action为处理文件的路径

 

 <form id="fileUpload" action="excel.do?method=exportMemberExcel" enctype="multipart/form-data" method="post">      <input id="excelFile" name="file" type="file"/>      <input type="button" value="http://www.mamicode.com/提交" onclick="submitExcel()"/>  </form>

 

2)js文件:

通过js文件对上传的文件进行初识的格式验证,判断是否为空以及格式是否正确,正确的话提交表单,由后台对上传的文件处理,此处用的是jQuery,需要导入jquery-***.js,此处使用的是jquery-1.4.2.min.js(最后提供下载地址)。

 

function submitExcel(){       var excelFile = $("#excelFile").val();       if(excelFile==‘‘) {alert("请选择需上传的文件!");return false;}       if(excelFile.indexOf(‘.xls‘)==-1){alert("文件格式不正确,请选择正确的Excel文件(后缀名.xls)!");return false;}       $("#fileUpload").submit();    }

 

3)Action中:

使用common-fileupload包中的类FileItemFactory,ServletFileUpload对请求进行处理,如果是文件,用工具累ExcelUtil处理,不是文件,此处未处理,不过以后开发可以根据需要处理,此处不纍述。(因为如果Excel中如果存在错误记录,还需供用户下载,所以若有错误信息,暂保存在session中,待用户下载后可清空此session)。

 

 public ActionForward exportMemberExcel(ActionMapping actionMapping,          ActionForm actionForm, HttpServletRequest request,          HttpServletResponse response) throws Exception {      int maxPostSize = 1000 * 1024 * 1024;      FileItemFactory factory = new DiskFileItemFactory();      ServletFileUpload servletFileUpload = new ServletFileUpload(factory);      servletFileUpload.setSizeMax(maxPostSize);      try {      List fileItems = servletFileUpload.parseRequest(request);      Iterator iter = fileItems.iterator();      while (iter.hasNext()) {          FileItem item = (FileItem) iter.next();          if (!item.isFormField()) {// 是文件          Map map = ExcelUtil.excel2PhoneList(item.getInputStream());     String[][] error = (String[][]) map.get("error");          if (error.length != 0) {      //如果存在错误,存入内存,供用户保存      request.setAttribute("errorFlag", "ture");      request.getSession().setAttribute("exportMap", map);     } else {      request.setAttribute("errorFalg", "false");      // 获取正确的值填写json      String phoneJson = JsonUtil        .phoneArray2Json((String[][]) map          .get("current"));      request.setAttribute("phoneJson", phoneJson);     }    } else {    //不是文件,此处不处理,对于text,password等文本框可在此处理        logger.error("wrong file");    }   }  } catch (Exception e) {   logger.error("invoke fileUpload error.", e);  }  return actionMapping.findForward("queryAccounts"); }

 

4、工具类ExcelUtil

主要借助jxl包对Excel文件进行解析,获取正确信息以及错误信息,供用户取舍。

 

 public static Map excel2PhoneList(InputStream inputStream) throws Exception {     Map map = new HashMap();     Workbook workbook = Workbook.getWorkbook(inputStream);  //处理输入流     Sheet sheet = workbook.getSheet(0);// 获取第一个sheet     int rows = sheet.getRows();   //获取总行号     String[][] curArr = new String[rows][2];     //存放正确心细     String[][] errorArr = new String[rows * 2][4];   //存放错误信息     int curLines = 0;     int errorLines = 0;  for (int i = 1; i < rows; i++) {// 遍历行获得每行信息     String phone = sheet.getCell(0, i).getContents();// 获得第i行第1列信息     String shortNum = sheet.getCell(1, i).getContents();// 短号     StringBuffer errorMsg = new StringBuffer();     if (!isRowEmpty(sheet, i)) { //此行不为空        //对此行信息进行正误判断                }  }////正误信息存入map,保存  map.put("current", current);  map.put("error", error);   return map; }   private static boolean isRowEmpty(Sheet sheet, int i) {    String phone = sheet.getCell(0, i).getContents();// 集团编号    String shortNum = sheet.getCell(1, i).getContents();// 集团名称    if (isEmpty(phone) && isEmpty(shortNum))        return true;    return false;   }

 

返回值由Action处理,此处为止,Excel的解析就完成了!

3 生成Excel

上文中说到如果存在错误信息,可供用户下载,错误信息存在Session中,下载就需要利用Session中的数据生成Excel文档,供用户保存。

1)Action中:

Action从Session中获取保存的对象,调用工具类保存,然后删除Session中的内容.

 

 public ActionForward downErrorExcel(ActionMapping actionMapping,      ActionForm actionForm, HttpServletRequest request,      HttpServletResponse response) throws Exception {     Map map = (Map) request.getSession().getAttribute("exportMap");     ExcelUtil.createExcel(response, map);     request.getSession.removeAttribure("exportMap");     return null;    }

 

2)工具类ExcelUtil中:

 

 public static boolean createExcel(HttpServletResponse response, Map map) {     WritableWorkbook wbook = null;     WritableSheet sheet = null;     OutputStream os = null;     try {       response.reset();          //生成文件名       response.setHeader("Content-disposition", "attachment; filename="           + new String("错误信息".getBytes("GB2312"), "ISO8859-1")           + ".xls");       response.setContentType("application/msexcel");       os = response.getOutputStream();       wbook = Workbook.createWorkbook(os);       sheet = wbook.createSheet("信息", 0);       int row = 0;       //填写表头       setSheetTitle(sheet, row);       //遍历map,填充数据       setSheetData(sheet, map, row);       wbook.write();       os.flush();     } catch (Exception e) {       //自己处理     }finally {         try {//切记,此处一定要关闭流,否则你会下载一个空文件          if (wbook != null)              wbook.close();          if (os != null)              os.close();         } catch (IOException e) {            e.printStackTrace();         } catch (WriteException e) {            e.printStackTrace();      }  }  return false; } private static void setSheetTitle(WritableSheet sheet, int row)   throws RowsExceededException, WriteException {  // 设置excel标题格式  WritableFont wfont = new WritableFont(WritableFont.ARIAL, 12,    WritableFont.BOLD, false, UnderlineStyle.NO_UNDERLINE,    Colour.BLACK);  WritableCellFormat wcfFC = new WritableCellFormat(wfont);  //设置每一列宽度  sheet.setColumnView(0,13);  sheet.setColumnView(1,13);  sheet.setColumnView(2,13);  sheet.setColumnView(3,50);  //填写第一行提示信息  sheet.addCell(new Label(0, row, "手机号码", wcfFC));  sheet.addCell(new Label(1, row, "短号", wcfFC));  sheet.addCell(new Label(2, row, "原错误行号", wcfFC));  sheet.addCell(new Label(3, row, "错误原因", wcfFC)); } private static void setSheetData(WritableSheet sheet, Map map, int row)   throws RowsExceededException, WriteException {  WritableFont wfont = new WritableFont(WritableFont.ARIAL, 10,    WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE,    Colour.RED);  WritableCellFormat wcfFC = new WritableCellFormat(wfont);  //从map中获取数据  String[][] error = (String[][]) map.get("error");  //遍历并填充  for (int i = 0; i < error.length; i++) {   row++;   sheet.addCell(new Label(0, row, error[i][0]));   sheet.addCell(new Label(1, row, error[i][1]));   sheet.addCell(new Label(2, row, error[i][2]));   sheet.addCell(new Label(3, row, error[i][3],wcfFC));  } }

 

 

 

 

Excel文件生成之后,由response传给客户,客户选择路径,就可以下载了,至此,完成了Excel文件下载、解析、和生成的工作,大功一件,希望有所启发。

另外,补充一下,火狐fireFox在上传文件时,服务器端并不能获取客户端存取文件的绝对路径,而只是一个文件名,ie8以及低版本上传文件时,服务器可以获得绝对路径,这是火狐的安全机制决定的,所以试图根据上传的文件路径,对文件修改然后保存到原文件,这种是不可取的,一者是因为火狐下获取不到文件路径,二者即使服务器在ie下获得了文件的绝对路径,在创建并修改文件时也只是生成在服务器端,并不能修改客户端的文件,只是提醒下,网上有解决方法,可以自行查阅。