필수 셋팅
엑셀 다운로드시 추가 설정 사항을 적용하여 엑셀 다운로드를 할 수 있다
옵션 설정
옵션설정을 하지 않으면 모두 default
값으로 설정 된다header
, fileName
은 설정을 해주는 것이 좋다
설정가능한 옵션
title
: 엑셀 제목 (default: 제목없음)header
: 엑셀 헤더 (default: 조회된 컬럼명으로 헤더를 자동 생성함)fileName
: 엑셀 파일명 (default: export.xlsx)columnWidth
: 엑셀 컬럼 기본간격 설정값 엑셀 간격 폭을 넓힐때 설정 (default: 3000)style
: 기본적인 테두리 설정과 font 설정이 추가된다 다운로드시 속도가 저하된다 (default: false)autoSize
: 자동으로 컬럼을 리사이징 한다 (default: false)
package com.project.component.excel.domain.dto
/**
* 엑셀 다운로드 확장 도메인
*/
class ReqExcelDownload (
/* 엑셀 제목 */
var title: String? = null,
/* 엑셀 Header */
var header: Array<String> = arrayOf(),
/* 엑셀 fileName */
var fileName: String? = null,
/* 엑셀 컬럼 사이즈(지정하지 않으면 기본 사이즈(3000)가 지정된다) */
var columnWidth: Int? = null,
/* 스타일 여부 기본 false */
var style: Boolean = false,
/* 오토 컬럼 리사이징 사용 여부 기본 false */
var autoSize: Boolean = false
) {
override fun toString(): String {
return "ReqExcelDownload(title=$title, header=${header.contentToString()}, fileName=$fileName, columnWidth=$columnWidth, style=$style, autoSize=$autoSize)"
}
}
ExcelService
공통 엑셀 다운로드 서비스는 향상된 SXSSF 방식으로 엑셀 다운로드 서비스를 제공한다
별도의 flush 설정은 하지 않고 기본값을 사용한다
안정성: 30만건의 데이터까지 테스트 완료
SXSSF : XSSF의 Streaming Version으로 메모리를 적게 사용하여 대용량 엑셀 다운로드에 주로 사용되는 방식
SXSSF 방식 -> 생성자 방식에서의 기본 flush 크기는 100 이며, -1 지정시 무제한이다. 쓰기전용이며 읽기는 불가능하다
공통 엑셀 다운로드 서비스는 Object
와 Map
형태를 모두 지원한다
엑셀 다운로드 서비스 사용시 엑셀 다운로드를 사용할 서비스에서 ExcelService
를 의존성을 주입 받고 download
메서드만 호출해서List<Object>
또는 List<Map>
원하는 형태의 매개변수를 전달하여 사용하면 된다
소스코드
package com.project.component.excel.service
import com.project.component.excel.constant.ExcelConstant.Companion.EXCEL_XLSX_STREAMING_VIEW
import com.project.component.excel.domain.dto.ReqExcelDownload
import org.springframework.stereotype.Service
import org.springframework.web.servlet.ModelAndView
/**
* 엑셀 서비스
*/
@Service
class ExcelService(var excelConverter: ExcelConverter) {
/**
* 엑셀 다운로드 서비스
* Map 이나 객체 형태로 받아서 엑셀 파일로 만들어 리턴함
* 엑셀 다운로드 서비스를 이용하기 위해서 요청 파라메터는
* ReqExcel 엑셀 객체를 상속 받아서 파라메터로 전달해야함
* @param list
* @param <T>
* @return
</T> */
fun <T> download(list: MutableList<T>): ModelAndView {
return ModelAndView(EXCEL_XLSX_STREAMING_VIEW, excelConverter.convertList(list))
}
/**
* 엑셀 다운로드 서비스
* Map 이나 객체 형태로 받아서 엑셀 파일로 만들어 리턴함
* 엑셀 다운로드 서비스를 이용하기 위해서 요청 파라메터는
* ReqExcel 엑셀 객체를 상속 받아서 파라메터로 전달해야함
* @param list
* @param <T> 엑셀 변환 데이터
* @param <E extends ReqExcel> 엑셀 파라메터
* @return
</E></T> */
fun <T> download(list: List<T>, req: ReqExcelDownload): ModelAndView {
return ModelAndView(EXCEL_XLSX_STREAMING_VIEW, excelConverter.convertList(list, req))
}
}
사용법
엑셀 다운로드 서비스 사용시 엑셀 다운로드를 사용할 서비스에서 ExcelService
를 의존성을 주입 받고download
메서드만 호출해서 List<Object>
또는 List<Map>
원하는 형태의 매개변수를 전달하여 사용
- 엑셀 다운로드 서비스의 리턴 타입은
ModelAndView
로 설정 header
와fileName
을 설정하고excelService.download
를 호출
Sample 엑셀 다운로드 서비스 소스코드
조회된 데이터가 null
인 경우 빈 excel 파일을 export.xlsx
로 리턴해주므로 별도의 null
처리를 할 필요가 없다
package com.project.api.sample.service
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
@Service
class SampleExcelService(
val excelService: ExcelService
) {
val log: Logger = LoggerFactory.getLogger(this::class.java)
/**
* Sample 엑셀 다운로드 API
* @return
* @throws IOException
*/
@Throws(IOException::class)
fun getSampleExcel(): ModelAndView {
val dataList: List<SampleExcelDownload> = listOf(
SampleExcelDownload(
name="홍길동1",
email="aaa@aaa.com",
phone="010-1111-1111",
dept="서버팀",
workCode=1111,
deptCode=2222,
content="테스트 내용",
ip="123.123.123.123",
percent= BigDecimal("1.1234"),
createDate="2019-10-10T00:00",
updateDatetime="2019-03-10T06:30:30",
empty= null),
SampleExcelDownload(
name="홍길동2",
email="bbb@aaa.com",
phone="010-1111-2222",
dept="서버팀",
workCode=1111,
deptCode=2222,
content="테스트 내용",
ip="1.1.1.1",
percent= BigDecimal(1234.123455),
createDate="2019-10-10T00:00",
updateDatetime="2019-03-10T06:30:30",
empty=null)
)
return excelService.download(dataList,
ReqExcelDownload(
header = arrayOf("이름", "이메일", "전화번호", "소속부서", "업무코드", "부서코드", "내용", "IP", "소수", "날짜", "일시", "빈데이터"),
fileName = "샘플파일_${LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))}"
)
)
}
}
Sample 엑셀 다운로드 컨트롤러 소스코드
package com.project.api.sample.controller
import com.project.api.sample.service.SampleExcelService
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.core.io.Resource
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.io.IOException
@RestController
@RequestMapping("/sample")
@Tag(name = "[Sample] 공통 Excel", description = "SampleExcelController")
class SampleExcelController(
val sampleExcelService: SampleExcelService) {
@Operation(summary = "Sample 엑셀 양식 다운로드")
@GetMapping("/excelform")
@Throws(IOException::class)
fun getSampleExcelForm(): ResponseEntity<Resource> = sampleExcelService.getSampleExcelForm()
@Operation(summary = "Sample 엑셀 다운로드")
@GetMapping("/excel")
@Throws(IOException::class)
fun getSampleExcel() = sampleExcelService.getSampleExcel()
}
Sample 엑셀 다운로드 테스트코드
package com.project.api.sample.controller
import com.project.common.BaseMvcTest
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.print
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import javax.validation.Validator
/**
* 엑셀 공통 서비스 테스트
*/
class SampleExcelControllerTest(val validator: Validator): BaseMvcTest() {
@BeforeEach
fun beforeSetUp() {
applyEncodingFilter()
}
@Test
fun `엑셀 다운로드 테스트`() {
this.mockMvc
.perform(get("/sample/excel"))
.andExpect(status().isOk)
.andDo(print())
}
@Test
fun `엑셀 양식 다운로드 테스트`() {
this.mockMvc
.perform(get("/sample/excelform"))
.andExpect(status().isOk)
.andDo(print())
}
}
테스트 코드 공통 클래스
package com.project.common
import com.fasterxml.jackson.databind.ObjectMapper
import org.apache.commons.lang3.StringUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.mock.web.MockMultipartFile
import org.springframework.test.context.TestConstructor
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.print
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.web.context.WebApplicationContext
import org.springframework.web.filter.CharacterEncodingFilter
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
@SpringBootTest
@AutoConfigureMockMvc
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
class BaseMvcTest {
@Autowired
lateinit var mapper: ObjectMapper
@Autowired
lateinit var mockMvc: MockMvc
@Autowired
lateinit var ctx: WebApplicationContext
fun applyEncodingFilter() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.ctx)
.addFilters<DefaultMockMvcBuilder>(
CharacterEncodingFilter("UTF-8", true),
)
.alwaysDo<DefaultMockMvcBuilder>(print())
.build()
}
/**
* 파일 업로드 데이터 생성
* @param originalFileName 원본파일명
* @param reqFileName 요청파일명(API에서 받는 이름)
* @return
*/
fun getMultipartFile(originalFileName: String, reqFileName: String): MockMultipartFile {
return getMultipartFile(null, originalFileName, reqFileName)
}
/**
* 파일 업로드 데이터 생성
* @param originalFileName 원본파일명
* @param reqFileName 요청파일명(API에서 받는 이름)
* @return
*/
fun getMultipartFile(
fileMiddlePath: String?,
originalFileName: String?,
reqFileName: String?
): MockMultipartFile {
var filePath = Paths.get("src", "test", "resources", "file")
if (StringUtils.isNotEmpty(fileMiddlePath)) filePath = Path.of(filePath.toString(), fileMiddlePath)
filePath = Paths.get(filePath.toString(), originalFileName)
return MockMultipartFile(reqFileName!!, originalFileName, null, Files.readAllBytes(filePath))
}
}
'프로젝트' 카테고리의 다른 글
[OSS] 백오피스 Operation Support System 개발 가이드 (0) | 2021.08.22 |
---|---|
[Kotlin][SpringBoot Excel] 엑셀 업로드 공통 서비스 가이드 (0) | 2021.08.03 |
[SpringBoot test] Sample API 테스트 코드 (0) | 2020.06.20 |
[SpringBoot test] Sample API 및 Sample 객체 코드 (0) | 2020.06.20 |
[SpringBoot test] BaseTest 클래스 사용 가이드 (0) | 2020.06.20 |
댓글