본문 바로가기
웹개발지식쌓기

[back] 엑셀 파일 생성 및 다운로드 소스 구조

by developer_j 2023. 9. 1.
728x90
반응형

엑셀 파일 생성 및 다운로드 소스 구조 를 이해하기 위해 레거시 코드를 분석해보았다

1. 엑셀 파일 생성(엑셀 라이브러리 POI 사용)
2. response 객체에 엑셀파일 출력

전체코드는 제일 아래에!


 

1. 엑셀 파일 생성(엑셀 라이브러리 POI 사용)

우선 먼저, 엑셀 파일을 생성해준다. 엑셀 파일 생성에 필요한 기본 메소드는 아래와 같다.

- HSSFWorkbook workbook = new HSSFWorkbook();
  : workbook 생성자로 엑셀 파일 객체 생성
- HSSFSheet sheet = workbook.createSheet();
  : workbook 객체의 createSheet 메소드를 사용하여 시트 생성
- HSSFRow row = sheet.createRow(0);
  : sheet 객체의 createRow(index) 메소드를 사용하여 로우 생성
- HSSFCell cell00 = row.createCell(0); 
  : row 객체의 createCell(index) 메소드를 사용하여 셀 생성

엑셀파일 - 시트 - 로우 - 셀 순서로 차근차근 생성해준다.
지금은 테스트 차원에서 하나하나 인덱스를 지정해서 엑셀을 생성했지만,
쿼리로 리스트를 불러와서 세팅해줄 때는 for문을 사용하여 접근 및 세팅하도록 해주면 될 것 같다.

 

 

 

2. response 객체에 엑셀파일 출력

나는 파일 입출력에 대해 아직 많이 다뤄보지는 못했고 이해가 부족하다.
다만 엑셀 다운로드 소스들을 구글링 해 보았을 때, 대부분 아래와 같은 구성을 가진 듯 했다.

- 결과 객체에서 파일 입출력을 위한 outputStream을 얻고,
- 거기에다가 엑셀 파일을 write
- response 객체에 contentType과 fileName 헤더값 세팅
- outputStream을 close() 종료

즉,

workbook.write(response.getOutputStream());

결과 객체에서 outputStream을 얻고, 엑셀 파일을 write

response.setContentType("application/vnd.ms-excel");

response에 contentType 세팅

response.setHeader("Content-Disposition", "attachment; filename=" + fileName);

response에 fileName 헤더값 세팅

response.getOutputStream().close();

그리고 close() 호출로 stream 종료까지..

 

3. 추가로 알아낸 것 (ajax 사용 시 다운로드 안되는 문제)

나는 엑셀 다운로드 버튼을 눌렀을 때에 페이지 이동없이 다운로드 되는 것을 생각하면서,
처음에는 ajax로 이 소스를 호출하도록 하고 싶었다.

그래서 ajax를 사용하여 url을 호출했더니 다운로드가 안됐었는데, submit을 사용하니 다운로드가 되었다

 

ajax를 사용하면, response객체에 write해도 다운로드가 되지 않는다는 것을 알게 되었다.

이에 대해 다른 선임분께 여쭤봤더니 ajax가 response 객체를 기다리지 않아서, 그렇다고 했다. 

 

음..그렇다 아직 잘 모르겠다!!!!!!!!! 갈길이 멀구나 요것에 대해서는 따로 블로그 글을 파서 공부 해봐야 겠당^^7

 


< 전체 java 코드 >

	@RequestMapping("/excelDownload")
	@ResponseBody
	public void excelDownload(HttpServletRequest request, HttpServletResponse response) {
		// 엑셀 파일 생성
		HSSFWorkbook workbook = new HSSFWorkbook();
		
		// 엑셀 파일 sheet 생성(여러개 생성 가능)
		HSSFSheet sheet = workbook.createSheet();

		// 헤더 목적의 1번째 로우 생성
		HSSFRow header = sheet.createRow(0);
		// 헤더 목적의 1번째 로우 생성 > 1번째 cell 생성
		HSSFCell cell00 = header.createCell(0); 
		cell00.setCellValue("항목1");
		// 헤더 목적의 1번째 로우 생성 > 2번째 cell 생성
		HSSFCell cell01 = header.createCell(1); 
		cell01.setCellValue("항목2");
		
		// 데이터 목적의 2번째 로우 생성
		HSSFRow row1 = sheet.createRow(1);
		HSSFCell cell10 = row1.createCell(0); 
		cell10.setCellValue("데이터1_1");
		HSSFCell cell11 = row1.createCell(1); 
		cell11.setCellValue("데이터1_2");
		
		// 데이터 목적의 3번째 로우 생성
		HSSFRow row2 = sheet.createRow(2);
		HSSFCell cell20 = row2.createCell(0); 
		cell20.setCellValue("데이터1_1");
		HSSFCell cell21 = row2.createCell(1); 
		cell21.setCellValue("데이터1_2");
		
		OutputStream out = null;
		String fileName = "fileName.xls";
		try {

			ByteArrayOutputStream outByteStream	= new ByteArrayOutputStream();
			workbook.write(outByteStream);
			byte[] outArray	= outByteStream.toByteArray();

			response.setContentType("application/vnd.ms-excel");
			response.setContentLength(outArray.length);
			response.setHeader("Expires", "0");
			response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
			out	= response.getOutputStream();
			out.write(outArray);
			out.flush();
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != out) {
				try {
					out.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
			
	}

 

+) 위의 코드는 다른 레거시 코드들을 참조하여 내가 재구성한 것이다.

byteArrayOutputStream 에 한번 넣고, 그 결과 데이터를 response의 outputStream에 다시 출력시키고 있는데 왜 2중으로 구성되어있는지는 잘 모르겠다. 나중에 outputStream에 대해 다시 공부를 해서 이 글을 보충하러 와야겠다.

이 소스와 비슷하게 짜셨던 분이 있어 글을 가져옴..!

https://developer-davii.tistory.com/49

 

[JAVA] POI 엑셀파일 생성시, "XXX의 내용에 문제가 있습니다."

* JAVA POI 엑셀파일 생성시, "이 통합 문서의 내용을 복구하시겠습니까?" 에러 해결보자 최근 java POI를 사용하여 엑셀업로드 개발을 작업하고 있는데, 한가지 문제를 만났다. 엑셀 파일을 생성 후

developer-davii.tistory.com

 

728x90
반응형