


SpringBoot에서 프로젝트를 만들 때 기본적으로 추가할 수 있는 의존성을 의미합니다
Web
Thymeleaf
Lombok
엑셀 파일을 읽기 위해 필요한 poi, poi-ooxml과
확장자를 가져오기 위해 필요한 commons-io를 추가해줍니다.
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>3.11</version>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId> <!-- 엑셀 2007 이상 버전에서 사용 -->
  <version>3.11</version>
</dependency>
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8">
    <title>엑셀 업로드</title>
  </head>
  <body>
    <form th:action="@{/excel/read}" method="POST" enctype="multipart/form-data">
      <input type="file" th:name="file">
      <input th:type="submit" value="제출" />
    </form>
  </body>
</html>
엑셀 데이터들을 넣어놓을 객체를 만들어줍니다.
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ExcelData {
  private Integer num;
  private String name;
  private String email;
  
}
1) 엑셀 폼을 보여주는 매핑 메소드를 작성합니다.
2) @RequestParam을 이용해서 파일을 전달 받습니다. 자료형은 MultipartFile을 사용합니다.
3) 아까 추가해뒀던 commons-io에 있는 파일 확장자 가져오기 기능을 이용해서
apache tika 사용해서 더 정교하게 파일 타입 검사하기
- apache tika 라이브러리를 사용하면 파일 스트림의 앞에 매직 넘버를 읽어서 파일 타입을 유추하므로 확장자보다 좀 더 정확하게 읽을 수 있을 것 같습니다.
- 의존성 추가 (build.gradle)
- Tika 객체를 생성한 후에, detect(file)을 사용해서 MIME 타입 얻어내기 (ExcelController.java)
- MIME 타입이 원하는 타입인지 확인 (ExcelUtils.java)
.txt파일을.xlsx로 속인 후에 올리면, 확장자만 가지고 비교하면 잡을 수 없지만, apache tika를 사용하게 되면 MIME 타입을 통해 가짜 파일을 필터링할 수 있다는 장점이 있습니다.
4) 행 개수만큼 반복문을 돌며 데이터를 가져옵니다.
getCell(열 번호)를 통해 가져올 수 있으며, 아래와 같은 메소드를 제공합니다.
getNumericCellValue() : 실수 데이터 가져오기
getStringCellValue() : 문자열 데이터 가져오기
getBooleanCellValue() : 논리 데이터 가져오기
5) 엑셀 데이터들을 넣어놓은 객체 리스트들을 반환합니다.
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.FilenameUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@Controller
public class ExcelController {
  @GetMapping("/excel")
  public String main() { // 1
    return "excel";
  }
  @PostMapping("/excel/read")
  public String readExcel(@RequestParam("file") MultipartFile file, Model model)
      throws IOException { // 2
    List<ExcelData> dataList = new ArrayList<>();
    String extension = FilenameUtils.getExtension(file.getOriginalFilename()); // 3
    if (!extension.equals("xlsx") && !extension.equals("xls")) {
      throw new IOException("엑셀파일만 업로드 해주세요.");
    }
    Workbook workbook = null;
    if (extension.equals("xlsx")) {
      workbook = new XSSFWorkbook(file.getInputStream());
    } else if (extension.equals("xls")) {
      workbook = new HSSFWorkbook(file.getInputStream());
    }
    Sheet worksheet = workbook.getSheetAt(0);
    for (int i = 1; i < worksheet.getPhysicalNumberOfRows(); i++) { // 4
      Row row = worksheet.getRow(i);
      ExcelData data = new ExcelData();
      data.setNum((int) row.getCell(0).getNumericCellValue());
      data.setName(row.getCell(1).getStringCellValue());
      data.setEmail(row.getCell(2).getStringCellValue());
      dataList.add(data);
    }
    model.addAttribute("datas", dataList); // 5
    return "excelList";
  }
}
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body>
  <table class="table table-striped">
    <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">이름</th>
      <th scope="col">이메일</th>
    </tr>
    </thead>
    <tbody>
    <tr th:each="data : ${datas}" >
      <td scope="row" th:text="${data.num}"></td>
      <td th:text="${data.name}"></td>
      <td th:text="${data.email}"></td>
    </tr>
    </tbody>
  </table>
</body>
</html>
엑셀 import만 나흘 동안 찾다가 겨우 발견했네요😭 생명의 은인이십니다
감사합니다