본문 바로가기
실습/[스프링 부트] 채팅 웹 사이트 만들기

[JAVA] OpenCSV를 사용한 CSV 파일 만들기

by 이민우 2024. 4. 1.
728x90
반응형

이전 포스팅에 이어간다.

https://123okk2.tistory.com/509

 

[JAVA] OpenCSV를 이용한 CSV 파싱

프로젝트 내 요구사항 중에는 아래와 같은 요구사항이 존재했다. 사용자가 엑셀 혹은 csv 파일을 서버에 업로드할 수 있을 것 사용자가 엑셀 혹은 csv 파일을 서버에서 다운로드할 수 있을 것 사

123okk2.tistory.com

 

이번에는 OpenCSV를 활용한 csv 파일 만들기이다.

 

DB에서 데이터를 가져왔다 가정하고, 해당 데이터를 csv 팡ㄹ로 만들어 사용자에게 파일을 제공하는 코드를 공유하려고 한다.

 

코드 작성

작성 방법은 별게 없다. 그냥 String[]을 CSVReader.writeNext()의 파라미터로 입력만 해주면 된다.

 

DownloadService.java

package com.mwlee.test.service;

import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;

import com.opencsv.CSVWriter;

import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class DownloadService {
	
	// 엑셀 파일로 만들 데이터
	// 실구현에서는 DB에서 쿼리 결과로 가져온 것.
	private List<Map<String, Object>> result = new ArrayList<>();
	
	
	/**
	 * 원래는 DB에서 데이터를 빼와야하지만,
	 * 굳이 그럴 필요 없으므로 가라 데이터 생성
	 */
	@PostConstruct
	private void setDate() {
		// result 세팅
		// 컬럼들
		String[] columns = new String[] {
				"col_1",
				"col_2",
				"col_3"
		};
		
		Map<String, Object> firstRow = new HashMap<>();
		firstRow.put(columns[0], 1);
		firstRow.put(columns[1], "a");
		firstRow.put(columns[2], "20240101");
		result.add(firstRow);
		
		// 1번 데이터 빼기
		Map<String, Object> secondRow = new HashMap<>();
		secondRow.put(columns[0], 2);
		secondRow.put(columns[2], "20240102");
		result.add(secondRow);
		
		// 3번 데이터 빼기
		Map<String, Object> thirdRow = new HashMap<>();
		thirdRow.put(columns[0], 3);
		thirdRow.put(columns[1], "b");
		result.add(thirdRow);
	}
	
	/**
	 * CSV 파일을 만들어 전송
	 * @return
	 */
	public byte[] generateCsv() {

		try {
			// 필요 stream 및 writer 선언
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            Writer writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
            CSVWriter csvWriter = new CSVWriter(writer);
            
        	// 맨 위에 각 컬럼명 작성
        	List<String> keys = new ArrayList<>(result.get(0).keySet());
        	csvWriter.writeNext(keys.toArray(new String[0]));
        	
        	// 둘째 줄부터 데이터 삽입
        	for(Map<String, Object> data : result) {
        		// row 생성
        		// keys의 length 만큼 row 생성
        		String[] rowData = new String[keys.size()];
        		int index = 0;
        		for(String key : keys) {
        			if(data.get(key) == null) {
        				// 데이터가 없으면 빈 값
        				rowData[index++] = "";
        			}
        			else {
        				// 데이터가 존재하면 String으로 변환해서 입력
        				rowData[index++] = data.get(key).toString();
        			}
        		}
        		csvWriter.writeNext(rowData);
        	}

        	// csvWriter close 및 byte[]를 return
        	csvWriter.close();
        	return outputStream.toByteArray();
		}
		catch(Exception e) {
			e.printStackTrace();
			return new byte[] {};
		}
	}
}

 

이제 서비스에서 파일을 가져와 사용자에게 다운로드 파일을 제공하는 컨트롤러이다.

 

DownloadRestController.java

package com.mwlee.test.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DownloadRestController {
	@Autowired DownloadService service;
	
	@GetMapping("/download/csv")
	public ResponseEntity<Resource> downloadCsv() {
		
		byte[] excelData = service.generateCsv();
		
		if(excelData == null || excelData.length == 0) {
			return ResponseEntity.internalServerError().build();
		}
		
		Resource resource = new ByteArrayResource(excelData);
		
		return ResponseEntity.ok()
				.contentType(
						MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
				)
				// 파일명 입력
				.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"test-download-csv.csv\"")
				.body(resource);
	}
}

 

 

테스트

위에서 입력한 /download/csv url로 들어가서 파일을 다운로드받아보자.

 

 

728x90
반응형