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

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

   1.Excel的下载

     1)Action中:

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

        public ActionForwarddownLoadExcelModel(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(StringfilePath,
       HttpServletResponse response, String fileName, StringfileType)
       throws Exception {
        Filefile = newFile(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 = newBufferedOutputStream(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="提交"οnclick="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)!");returnfalse;}
      $("#fileUpload").submit();
    }

   3)Action中:

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

     public ActionForwardexportMemberExcel(ActionMapping actionMapping,
         ActionForm actionForm, HttpServletRequest request,
         HttpServletResponse response) throws Exception {
     int maxPostSize = 1000 * 1024 * 1024;
     FileItemFactory factory = new DiskFileItemFactory();

      ServletFileUploadservletFileUpload = new ServletFileUpload(factory);
     servletFileUpload.setSizeMax(maxPostSize);

     try {
      ListfileItems = 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
      StringphoneJson = JsonUtil
        .phoneArray2Json((String[][])map
          .get("current"));
      request.setAttribute("phoneJson",phoneJson);
     }
    }else{    //不是文件,此处不处理,对于text,password等文本框可在此处理
       logger.error("wrong file");
    }
   }
  } catch (Exception e) {
   logger.error("invokefileUpload error.", e);
  }
  returnactionMapping.findForward("queryAccounts");
 }
  
4、工具类ExcelUtil

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

   public static Map excel2PhoneList(InputStreaminputStream) throws Exception {
    Map map = new HashMap();
    Workbook workbook =Workbook.getWorkbook(inputStream);  //处理输入流
    Sheet sheet = workbook.getSheet(0);// 获取第一个sheet
    int rows =sheet.getRows();   //获取总行号
    String[][] curArr = newString[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列信息

    StringshortNum = 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();// 集团编号
    StringshortNum = sheet.getCell(1, i).getContents();// 集团名称
    if(isEmpty(phone) &&isEmpty(shortNum))
       return true;
    returnfalse;
   }

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

  3 生成Excel

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

   1)Action中:

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

   public ActionForward downErrorExcel(ActionMappingactionMapping,
     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 booleancreateExcel(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 voidsetSheetTitle(WritableSheet sheet, int row)
   throwsRowsExceededException, WriteException {
  // 设置excel标题格式
  WritableFont wfont = newWritableFont(WritableFont.ARIAL, 12,
    WritableFont.BOLD,false, UnderlineStyle.NO_UNDERLINE,
    Colour.BLACK);
  WritableCellFormat wcfFC = newWritableCellFormat(wfont);

  //设置每一列宽度
  sheet.setColumnView(0,13);
  sheet.setColumnView(1,13);
  sheet.setColumnView(2,13);
  sheet.setColumnView(3,50);

  //填写第一行提示信息

  sheet.addCell(newLabel(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 voidsetSheetData(WritableSheet sheet, Map map, int row)
   throwsRowsExceededException, WriteException {
  WritableFont wfont = newWritableFont(WritableFont.ARIAL, 10,
    WritableFont.NO_BOLD,false, UnderlineStyle.NO_UNDERLINE,
    Colour.RED);
  WritableCellFormat wcfFC = newWritableCellFormat(wfont);

  //从map中获取数据
  String[][] error = (String[][])map.get("error");

  //遍历并填充
  for (int i = 0; i< error.length; i++) {
   row++;
   sheet.addCell(newLabel(0, row, error[i][0]));
   sheet.addCell(newLabel(1, row, error[i][1]));
   sheet.addCell(newLabel(2, row, error[i][2]));
   sheet.addCell(newLabel(3, row, error[i][3],wcfFC));
  }
 }

 

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值