Framework & Library/Spring & String boot

[Spring] ModelAndView로 파일 다운로드 (@Component, Bean 등록)

yjkim_97 2020. 12. 30. 14:25

직접 개발한 클래스를 Bean으로 등록하여, 파일 다운 다운로드 기능을 제공한다.

Bean으로 생성 시 @Component어노테이션을 사용하고, @ComponentScan어노테이션으로 Bean으로 등록해준다.

@Component어노테이션으로 생성된 Bean을 등록시키는 방법은 두 가지다.
1. ApplicationContext.xml에 <bean id="jeongpro" class="jeongpro" /> 이런 식으로 xml에 bean을 직접 등록
2. @ComponentScan(basePackages = { "com.kt.tbb.iptv.coupon.config", "com.kt.tbb.iptv.coupon.business" }) 식으로 어노테이션을 사용하여 등록

 


1. @ComponentScan

@ComponentScan 어노테이션은 @Component 어노테이션 및 streotype(@Service, @Repository, @Controller) 어노테이션이 부여된 클래스들을 자동으로 스캔하여 Bean으로 등록해주는 역할을 한다.

 

basePackages

@ComponentScan(basePackages = { "com.kt.tbb.iptv.coupon.config", "com.kt.tbb.iptv.coupon.business" })
public class CouponBaseLauncher {}

패키지 경로를 직적 적어 스캔할 위치를 지정할 수 있다.

 

 

basePackageClasses

@ComponentScan(basePackagesClass = Application.class)
public class CouponBaseLauncher {}

괄호 안에 적힌 Class가 위치한 곳에서부터 모든 어노테이션이 부여된 클래스를 Bean으로 등록해준다. (Class를 통해 스캔한다.)

 

2. @Component 부여한 Bean생성 - 파일 다운로드 클래스

상위 메서드로부터 다운로드할 파일의 정보(파일의 경로, 파일 Mime, 표기할 파일명)가 담긴 DownloadFile객체를 인자로 받아 처리 해당 파일을 다운로드하는 기능을 제공하는 클래스이다.

@Component 어노테이션으로 Bean으로 등록시킨다.

package com.kt.tbb.iptv.coupon.config;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.AbstractView;

import com.kt.tbb.iptv.coupon.framework.exceptions.CpnRuntimeException;
import com.kt.tbb.iptv.coupon.framework.util.DownloadFile;
import com.kt.tbb.iptv.coupon.framework.util.ResourceScanner;



@Component("downloadFileView")
public class DownloadFileView extends AbstractView {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(ResourceScanner.class);
	
	@Override
	protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) {
		
        // 상위 메서드에서 넘겨받은 인자값
        DownloadFile downloadFile = (DownloadFile) model.get("downloadFile");

		FileInputStream fin = null; // 파일을 읽기위한 객체
		OutputStream fout = null; // 파일을 내보내기 위한 객체
		try {
        
			String fileName = downloadFile.getEncodedFileName(request);
            
            		// 응답 서블릿 헤더에 내보낼 파일의 정보 기록
			response.reset();
			response.setContentType(downloadFile.getFileMime() + "; charset=UTF-8");
			response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
			response.setHeader("Content-Transfer-Encoding", "binary");
			response.setHeader("Content-Length", "" + downloadFile.getFileSize());
            
            		// 다운로드 대상인 파일을 읽어옴.
			fin = new FileInputStream(downloadFile.getFile());
			byte[] readBuffer = new byte[8192]; // 8K 버퍼
            
            		// 읽어온 파일을 OutPut 스트림 객체에 씀
			fout = response.getOutputStream();
			int numOfBytes = -1;
            
			while ((numOfBytes = fin.read(readBuffer)) != -1) {
				fout.write(readBuffer, 0, numOfBytes);
				fout.flush();
			}
            
		} catch (IOException e) {
			throw new CpnRuntimeException(e);
		} finally {
			try {
				if (fin != null) {
					fin.close();
				}
			} catch (IOException ex) {
				LOGGER.error(ex.toString(), ex);
			} finally {
				fin = null;
			}
			try {
				if (fout != null) {
					fout.close();
				}
			} catch (IOException ex) {
				LOGGER.error(ex.toString(), ex);
			} finally {
				fout = null;
			}
			downloadFile.dispose();
		}
	}
}

 

3. 상위 메서드에서 ModelAndView로 파일 다운로드

	// 프로모션 쿠폰 발행대상자 엑셀양식다운로드
	@GetMapping(value = "/v1/iss/target/excel/down/{excelType}/form")
	public ModelAndView issExcelFormDownload(@PathVariable(value="excelType") String excelType, HttpServletRequest request, PromCpnType promCpnType) {
		File file = new File(request.getSession().getServletContext().getRealPath("/excel/file/filename.xlsx"));
		DownloadFile downloadFile = new DownloadFile();
		downloadFile.setFile(file);
		downloadFile.setFileMime("application/octet-stream");
		downloadFile.setFileName(excelFilename);
		return new ModelAndView("downloadFileView", "downloadFile", downloadFile);
	}