본문 바로가기
IT 자료

java 엑셀 업로드 XSSFWorkbook 에러

by 성곤 2018. 6. 18.
반응형

 

java 엑셀 업로드 XSSFWorkbook


엑셀의 용량은 18MB, 열은 80개, 행은 5만 건 정도 된다.


값의 양이 그렇게 많다고 부르기에는 애매하긴한데, 어쨋든 작업도중에 서버가 에러를 뿜뿜한다.


out of memory...



java 소스 상에서


1
2
3
4
5
6
7
8
9
10
11
12
Workbook wb;
String fileName = excelFile.getName();
String fileSuffix = fileName.substring(fileName.lastIndexOf("."+ 1);
if (fileSuffix.equals("xls")) {
    wb = new HSSFWorkbook(excelFile.getInputStream());
else {
    OPCPackage pkg = OPCPackage.open(excelFile.getInputStream());
    wb = new XSSFWorkbook(pkg); // 바로 여기에서 멈춰버린다.
}
 
 
 
cs


여기저기 찾아보니깐, 그냥 poi의 버그같은거? 라고 한다.


성능 자체가 좋지 않다고 이야기가 있다.


최신버전을 사용해라, 라는 이야기도 있다.


어쨋든 이 문제는 org.apache.poi.xssf.usermodel.XSSFWorkbook.XSSFWorkbook(OPCPackage pkg)를 사용하면 안된다고 한다. 더 나은 방법이 있는지 찾아봤다.





엑셀 업로드 시에 매우 빠른 성능을 가지는 소스를 찾았다.


출처 : https://www.programcreek.com/java-api-examples/?code=jeevatkm/excelReader/excelReader-master/src/test/java/com/myjeeva/poi/ExcelWorkSheetRowCallbackHandlerTest.java#



해당 소스를 이용하니, 5만건을 "List<Map<String, String>>"형식으로 만들어주는데 약 3초정도 걸렸다.

 

 
 

붉은 색 네모부분의 소스를 모두 모아서 이클립스에 넣어주자.

poi.zip


출처의 사이트를 보면 샘플파일까지 다 있다.


붙여넣는 것까지 내가 도와줄 수는 없지만,

개인적으로 엑셀파일을 List<Map<String, String>> 형식으로 리턴받을 수 있게 조금 고쳐보았다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  /**
     * 엑셀파일 데이터 read
     * @param MultipartFile excelFile
     * @param Map<String, String> paramMap
     * @return List<Map<String, String>> 엑셀 데이터
     * @throws Exception
     */
    public List<Map<StringString>> outDataList (MultipartFile excelFile, Map<StringString> paramMap) throws Exception {
       
       
        OPCPackage pkg = null;
 
        InputStream inputStream = excelFile.getInputStream();       
       
        final List<Map<StringString>> excelDataList = new ArrayList<Map<StringString>>();   
        final String test_id = paramMap.get("test_id");
           
       ExcelWorkSheetRowCallbackHandler sheetRowCallbackHandler = new ExcelWorkSheetRowCallbackHandler(
            new ExcelRowContentCallback()  {
                @Override
                public void processRow(int rowNum, Map<StringString> map) throws Exception {
 
                        //엑셀에 없는 데이터를 MAP 에 담는다
                        map.put("test_id", test_id);
                        excelDataList.add(map);
                }
        });
       
        pkg = OPCPackage.open(inputStream);
        ExcelSheetCallback sheetCallback = new ExcelSheetCallback() {
           
            private int sheetNumber = 0;
           
            @Override
            public void endSheet() throws Exception{
            }
 
            @Override
            public void startSheet(int sheetNum, String sheetName) throws Exception{
                this.sheetNumber = sheetNum;       
            }
        };
        ExcelReader example1 = new ExcelReader(pkg, sheetRowCallbackHandler, sheetCallback);           
        example1.process();
 
        IOUtils.closeQuietly(inputStream);
 
           return excelDataList;
    }
cs



반응형