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만 나흘 동안 찾다가 겨우 발견했네요😭 생명의 은인이십니다
감사합니다