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);
}