導入EXcel工具類

一、概述

在工作過程中,都會遇到這樣一個需求,就是將相關的Excel中的數據導入數據庫,這裏寫成通用的導入Excel的工具。

二、項目實現

1、構建pom.xml

我的工程是利用Maven來構建的,這裏僅給出最核心的包

<dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <version>2.6</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-scratchpad</artifactId>
    <version>3.11-beta2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.11-beta2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>3.11-beta2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-excelant</artifactId>
    <version>3.11-beta2</version>
</dependency>
<!-- excel上傳用 -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

導入之前需要先下載要導入的Excel模板,把數據填寫到Excel,然後在導入到數據庫中

2.下載Excelm模板通用工具類

/**
     *
     * 2003導出下載Excel模板
     * @param fileName    文件名
     * @param titles      導出excel標題
     * @param hashMapKeys 導出excel顯示的列頭(對應pojo裏面的屬性)
     * @Description: 2003版本最大支持65536行
     */
    public static void exportExcelTemplate(String fileName, String[] titles, String[] hashMapKeys,HttpServletResponse response) throws IOException{
        // 1.創建工作簿
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 2.在workbook中添加一個sheet,對應Excel文件中的fileName
        HSSFSheet sheet = workbook.createSheet(fileName);

        // 樣式1:定義列寬
        for (int i = 0; i < 100; i++) {
            sheet.setColumnWidth(i, 6000);
        }

        //基礎樣式
        HSSFCellStyle baseStyle = workbook.createCellStyle();
        //設置單元格居中
        baseStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 左右居中
        baseStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 上下居中

        //設置邊框
        baseStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);  //下邊框
        baseStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);    //左邊框
        baseStyle.setBorderTop(HSSFColor.BLACK.index); //上邊框
        baseStyle.setBorderRight(HSSFColor.WHITE.index); //右邊框
        //設置自動換行
        baseStyle.setWrapText(true);

        //樣式2:定義第一行單元格樣式
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        //設置字體
        HSSFFont font = workbook.createFont();
        font.setFontName("宋體");
        font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
        // 字體大小
        font.setFontHeightInPoints((short) 12);
        cellStyle.setFont(font);
        //設置單元格居中
        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

        //樣式3:定義標題單元格樣式
        HSSFCellStyle cellStyle1 = workbook.createCellStyle();
        cellStyle1.cloneStyleFrom(baseStyle);
        //設置字體
        HSSFFont font1 = workbook.createFont();
        font1.setFontName("楷體");
        font1.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        font1.setFontHeightInPoints((short) 12);// 字體大小
        font1.setColor(HSSFColor.RED.index);//設置紅色
        cellStyle1.setFont(font1);
        //設置背景色
        cellStyle1.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        cellStyle1.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());

        //樣式4:定義內容欄單元格樣式
        HSSFCellStyle cellStyle2 = workbook.createCellStyle();
        cellStyle2.cloneStyleFrom(baseStyle);
        //設置字體
        HSSFFont font2 = workbook.createFont();
        font2.setFontName("宋體");
        font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
        // 字體大小
        font2.setFontHeightInPoints((short) 12);
        cellStyle2.setFont(font2);
        //設置單元格居左和居上
        HSSFDataFormat format=workbook.createDataFormat();
        cellStyle2.setDataFormat(format.getFormat("@"));

        //樣式5:定義尾部欄註釋單元格樣式
        HSSFCellStyle cellStyle3 = workbook.createCellStyle();
        HSSFFont font3 = workbook.createFont();
        font3.setFontName("楷體");
        font3.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        font3.setFontHeightInPoints((short) 12);// 字體大小
        font3.setColor(HSSFColor.RED.index);//設置紅色
        cellStyle3.setFont(font3);
        //樣式6:合併第一行單元格
//        Region region1 = new Region(0, (short) 0, 0, (short) (titles.length - 1));
//        sheet.addMergedRegion(region1);
        //2.創建頂行
        HSSFRow rowhead = sheet.createRow(0);
        rowhead.setHeight((short) 700);
        HSSFCell cellhead = rowhead.createCell(0);
        cellhead.setCellValue(fileName.substring(0, fileName.lastIndexOf(".")));
        cellhead.setCellStyle(cellStyle);

        //3.創建標題行
        HSSFRow row = sheet.createRow(0);
        // row.setHeight((short) 550);
        for (int i = 0; i < titles.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellValue(titles[i]);
            cell.setCellStyle(cellStyle1);
        }
        //4.創建key行
        HSSFRow rowi=sheet.createRow(2);
        for (int i = 0; i <  hashMapKeys.length; i++) {
            HSSFCell cell = rowi.createCell(i);
            cell.setCellValue(hashMapKeys[i]);
            cell.setCellStyle(cellStyle1);
        }
        HSSFRow row3=sheet.createRow(3);
        for (int i = 0; i <  hashMapKeys.length; i++) {
            HSSFCell cell = row3.createCell(i);

            cell.setCellStyle(cellStyle2);
        }
        //6.輸出到Excel表格
        //設置響應頭
        if (fileName.endsWith("xlsx")) {
            // response.setContentType("application/vnd.ms-excel");
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        } else {
            response.setContentType("application/vnd.ms-excel");
        }
        response.setHeader("Content-disposition", "attachment; fileName=" + URLEncoder.encode(fileName, "UTF-8"));
        OutputStream out = response.getOutputStream();
        workbook.write(out);
        out.flush();
        out.close();

    }

3.下載Excel模板Controller

import com.htf.utils.ExcelUtils;
import com.htf.utils.ImportExcelUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;

@Controller
public class ExportExcelController {

public static final String[] KEYS = {"id", "name", "age"};

/**
 * @param : [map, response]
 * @return : void
 * @date : 2018/10/27 16:08
 * @exception:
 * @Description: 下載excel2003模板測試  
 */
@RequestMapping("/downloadTemplate.do")
public void downTemplate(@RequestParam HashMap<String, Object> map, HttpServletResponse response) {
    List<Map> list = new ArrayList<>();
    //必填字段
    String[] key = ExportExcelController.KEYS;
    String[] titles = new String[]{"名稱", "性別", "年齡", "學校", "班級"};
    String fileName = "報表.xls";
    try {
        ExcelUtils.exportExcelTemplate(fileName, key, titles, response);
        response.getOutputStream().close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

4.測試下載Excel模板

模板內容如下圖

 

5.導入Excel工具類

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ImportExcelUtils {

/**
 *          導入excel
 * @param : file        文件
 * @param : startRow    起始行
 * @param : startColumn 起始列
 * @param : endRow
 * @param : endColumn
 * @return : java.util.List<java.lang.String[]>
 * @date : 2018/10/27 16:15
 * @exception:
 * @Description: 解析excel表XSSF  List<String[]>,適用於2007擠以上版本的excel,後綴名爲.xlsx或.xls文件
 * 默認解析工作簿中的第一張表,如果endRow=-1則默認解析最後一行,如果endColumn=-1則默認解析到startRow行的最後一列,後面的空行也會解析
 * 輸入的4個參數第幾行和第幾列都是從1算起,都是字面上的行或列,解析excel時會將所以單元格的類型轉化爲String類型,沒有值的單元格默認值爲"",
 * 沒有任何值的空行會跳過處理
 */
public static List<String[]> importExcel(File file, int startRow, int startColumn, int endRow, int endColumn) throws Exception {
    try {
        //導入excel文件,獲取工作簿
        Workbook workbook = WorkbookFactory.create(file);
        //獲取excel工作表對象,默認去第一個
        Sheet sheet = workbook.getSheetAt(0);
        //設置默認值,行數從0算起的,列數從1算起的
        if (endRow == -1) endRow = sheet.getLastRowNum() + 1;
        if (endColumn == -1) endColumn = sheet.getRow(startRow - 1).getLastCellNum();
        //定義集合
        List<String[]> list = new ArrayList<>();
        //給集合中添加數據
        for (int i = startRow - 1; i < endRow; i++) {
            Row r = sheet.getRow(i);
            if (null == r) continue;
            String[] strArr = new String[endColumn - startColumn + 1];
            for (int j = startColumn - 1; j < endColumn; j++) {
                //轉化單元格的類型爲String類型
                if (null != r.getCell(j)) {
                    r.getCell(j).setCellType(Cell.CELL_TYPE_STRING);
                    strArr[j] = r.getCell(j).getStringCellValue();
                    continue;
                }
                strArr[j] = "";
            }
            list.add(strArr);
        }
        return list;
    } catch (Exception e) {
        throw new Exception(e.getMessage());
    }
}

6.導入Excel Controller代碼

import com.htf.service.ExportExcelService;
import com.htf.utils.ExcelUtils;
import com.htf.utils.ImportExcelUtils;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @Auther: admin
 * @Date: 2018/10/1 21:18
 * @Description:上傳Excel
 */
@Controller
public class ExportExcelController {
   
 /** 
    * @date   : 2018/10/28 11:22   
    * @param  : [request, file, response] 
    * @return : java.lang.String 
    * @exception:
    * @Description: 導入Excel
    * 
    */  
    @RequestMapping("/importExcel.do")
    public String importExcel(HttpServletRequest request, @RequestParam("file") CommonsMultipartFile file, HttpServletResponse response) {
        StringBuffer buffer = new StringBuffer();
        //根據指定類的相對路徑來查找
        Resource resource = new ClassPathResource("../exportTemplate", this.getClass());
        String name = file.getOriginalFilename();
        //只能上傳.xls後綴的文件
        if (!name.endsWith(".xls") && !name.endsWith(".xlsx")) {
            buffer.append("必須使用下載模板上傳");
        }
        try {
            if (!resource.exists()) {
                resource.getFile().mkdir();
            }
            File fileExcel = new File(resource.getFile().getPath() + "/" + name);
            file.getFileItem().write(fileExcel);
            //解析文件
            List<String[]> list = ImportExcelUtils.importExcel(fileExcel, 1, 1, -1, -1);
            //定義信息結果字符串
            //定義上傳成功計數器
            int count = 0;
            //對解析的模板進行校驗
            //1.校驗模板是否正確
            if (!("類型".equals(list.get(0)[0]) && "數據".equals(list.get(0)[1]))) {
                buffer.append("您的模板不正確,第一行第一格必須是類型,第二行第二格必須是數據!!!");
            }
            //校驗是否爲XSS代碼
//            for (int i = 1; i < list.size(); i++) {
//                if (XssInterceptor.matches(list.get(i)[1])) {
//                    buffer.append("該模板裏存在惡意代碼,請檢查後重新上傳");
//                }
//            }
            if (list.size() == 0) {
                buffer.append("模板數據爲空");
            }
            for (int i = 1; i < list.size(); i++) {
                //校驗爲空的單元格
                if (StringUtils.isBlank(list.get(i)[0]) || StringUtils.isBlank(list.get(i)[1])) {
                    buffer.append("第" + (i + 1) + "行數據爲空,不能正確導入");
                    continue;
                }
                //2.校驗單元格長度大於100字符
                if (list.get(i)[1].length() >= 100) {
                    buffer.append("第" + (i + 1) + "行導入的字符數超過100字,不能正確導入");
                    continue;
                }
                //4.校驗數據是否重複
                HashMap map = new HashMap();
                map.put("id", list.get(i)[0]);
                map.put("name", list.get(i)[1]);
                continue;
            }
            //5存入數據庫
            HashMap hashMap = new HashMap();
            hashMap.put("id", "");

            //存入數據庫,調用service裏面的方法插入,(傳入參數是hashMap)
            // excelService.insert(hashMap);
            if (count == 0) {
                buffer.append("模板數據全部爲已導入的重複數據!");

            } else {
                buffer.append("共存入" + count + "條數據!");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "xxx頁面";
    }
}

7.校驗是否爲XSS,需要實現 HandlerInterceptor接口

package com.htf.Interceptor;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;


public class XssInterceptor implements HandlerInterceptor {

    private static Logger logger = LoggerFactory.getLogger(XssInterceptor.class);
    private static Pattern XSS_PATTERN;

    // 匹配含有字符:<
    public static String regex = ".*<.*";
    // 匹配含有字符: alert( )
    public static String regex1 = ".*[A|a][L|l][E|e][R|r][T|t]\\s*\\(.*\\).*";
    // 匹配含有字符: window.location =
    public static String regex2 = ".*[W|w][I|i][N|n][D|d][O|o][W|w]\\.[L|l][O|o][C|c][A|a][T|t][I|i][O|o][N|n]\\s*=.*";
    // 匹配含有字符:style = x:expression ( )
    public static String regex3 = ".*[S|s][T|t][Y|y][L|l][E|e]\\s*=.*[X|x]:[E|e][X|x].*[P|p][R|r][E|e][S|s]{1,2}[I|i][O|o][N|n]\\s*\\(.*\\).*";
    // 匹配含有字符: document.cookie
    public static String regex4 = ".*[D|d][O|o][C|c][U|u][M|m][E|e][N|n][T|t]\\.[C|c][O|o]{2}[K|k][I|i][E|e].*";
    // 匹配含有字符: eval( )
    public static String regex5 = ".*[E|e][V|v][A|a][L|l]\\s*\\(.*\\).*";
    // 匹配含有字符: unescape()
    public static String regex6 = ".*[U|u][N|n][E|e][S|s][C|c][A|a][P|p][E|e]\\s*\\(.*\\).*";
    // 匹配含有字符: execscript( )
    public static String regex7 = ".*[E|e][X|x][E|e][C|c][S|s][C|c][R|r][I|i][P|p][T|t]\\s*\\(.*\\).*";
    // 匹配含有字符: msgbox( )
    public static String regex8 = ".*[M|m][S|s][G|g][B|b][O|o][X|x]\\s*\\(.*\\).*";
    // 匹配含有字符: confirm( )
    public static String regex9 = ".*[C|c][O|o][N|n][F|f][I|i][R|r][M|m]\\s*\\(.*\\).*";
    // 匹配含有字符: prompt( )
    public static String regex10 = ".*[P|p][R|r][O|o][M|m][P|p][T|t]\\s*\\(.*\\).*";
    // 匹配含有字符: <script> </script>
    public static String regex11 = ".*<[S|s][C|c][R|r][I|i][P|p][T|t]>.*";
    // 匹配含有字符: <script> </script>
    public static String regex12 = ".*<[S|s][C|c][R|r][I|i][P|p][T|t]>.*</[S|s][C|c][R|r][I|i][P|p][T|t]>.*";
    // 匹配含有字符: 含有一個符號: 雙引號
    public static String regex13 = "[.&[^\"]]*\"[.&[^\"]]*";
    // 匹配含有字符: 含有一個符號: 單引號
    public static String regex14 = "[.&[^']]*'[.&[^']]*";
    // 匹配含有字符: 含有回車換行 和 <script> </script>
    public static String regex15 = "[[.&[^a]]|[|a|\n|\r\n|\r|\u0085|\u2028|\u2029]]*<[S|s][C|c][R|r][I|i][P|p][T|t]>.*</[S|s][C|c][R|r][I|i][P|p][T|t]>[[.&[^a]]|[|a|\n|\r\n|\r|\u0085|\u2028|\u2029]]*]";
    // 匹配含有字符: <script> </script>
    public static String regex16 = ".*<[J|j][A|a][V|v][A|a][S|s][C|c][R|r][I|i][P|p][T|t]>.*</[J|j][A|a][V|v][A|a][S|s][C|c][R|r][I|i][P|p][T|t]>.*";
    // 匹配含有字符: 含有回車換行 和 <script> </script>
    public static String regex17 = "[[.&[^a]]|[|a|\n|\r\n|\r|\u0085|\u2028|\u2029]]*<[J|j][A|a][V|v][A|a][S|s][C|c][R|r][I|i][P|p][T|t]>.*</[J|j][A|a][V|v][A|a][S|s][C|c][R|r][I|i][P|p][T|t]>[[.&[^a]]|[|a|\n|\r\n|\r|\u0085|\u2028|\u2029]]*]";

    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {
    }
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // Enumeration<String> params = request.getParameterNames();
        StringBuffer str = new StringBuffer();
        Map<String, String[]> map = request.getParameterMap();
        if (map != null && map.size() != 0) {
            Set<String> names = map.keySet();
            if (names != null && names.size() != 0) {
                Iterator<String> iterator = names.iterator();
                while (iterator.hasNext()) {
                    String value = request.getParameter(iterator.next());
                    str.append(value);
                }
            }
        }
        if (Pattern.compile(regex).matcher(str.toString()).matches() || Pattern.compile(regex1).matcher(str.toString()).matches() || Pattern.compile(regex2).matcher(str.toString()).matches() || Pattern.compile(regex3).matcher(str.toString()).matches()
                || Pattern.compile(regex4).matcher(str.toString()).matches() || Pattern.compile(regex5).matcher(str.toString()).matches() || Pattern.compile(regex6).matcher(str.toString()).matches()
                || Pattern.compile(regex7).matcher(str.toString()).matches() || Pattern.compile(regex8).matcher(str.toString()).matches() || Pattern.compile(regex9).matcher(str.toString()).matches() || Pattern.compile(regex10).matcher(str.toString()).matches() || Pattern.compile(regex11).matcher(str.toString()).matches() || Pattern.compile(regex12).matcher(str.toString()).matches() || Pattern.compile(regex13).matcher(str.toString()).matches() || Pattern.compile(regex14).matcher(str.toString()).matches() || Pattern.compile(regex15).matcher(str.toString()).matches() || Pattern.compile(regex16).matcher(str.toString()).matches() || Pattern.compile(regex17).matcher(str.toString()).matches())
        {

            logger.info("[attack] xss attack");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json");
            response.getWriter().print(JSON.toJSONString(AJAXResult.createErrorAjaxResult(AJAXCode.ParamsError), true));
            return false;
        } else {
            return true;
        }
    }
    public static boolean matches(String text) {
        if (text == null) {
            return false;
        }
        if (Pattern.compile(regex).matcher(text).matches() || Pattern.compile(regex1).matcher(text).matches() || Pattern.compile(regex2).matcher(text).matches() || Pattern.compile(regex3).matcher(text).matches() || Pattern.compile(regex4).matcher(text).matches() || Pattern.compile(regex5).matcher(text).matches() || Pattern.compile(regex6).matcher(text).matches() || Pattern.compile(regex7).matcher(text).matches() || Pattern.compile(regex8).matcher(text).matches() || Pattern.compile(regex9).matcher(text).matches() || Pattern.compile(regex10).matcher(text).matches() || Pattern.compile(regex11).matcher(text).matches() || Pattern.compile(regex12).matcher(text).matches() || Pattern.compile(regex13).matcher(text).matches() || Pattern.compile(regex14).matcher(text).matches() || Pattern.compile(regex15).matcher(text).matches() || Pattern.compile(regex16).matcher(text).matches() || Pattern.compile(regex17).matcher(text).matches()) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        Pattern pattern = Pattern.compile(regex1);
        CharSequence cs = "<Script>alert(\"test)</script>";
        System.out.println(pattern.matcher(cs).matches());
    }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章