가수면
파일 다운로드 기능 API 구현 본문
프론트에서 파일을 다운받기 위해 백엔드로 요청 보낼 때 백엔드에서 구성해야할 로직을 정리한다.
백엔드 (JAVA)
public void downloadFile(HttpServletResponse response,
String fileOriginNm,
String policyFileNm,
String policyFlpth) {
String uploadPath = policyFileService.getPolicyUploadFile(policyFlpth, policyFileNm); // uploadPath: WEB-INF/files/policy/upload/cisa_5g_strategy_508_1672216004129.pdf
File file = new File(uploadPath);
if (!file.exists()) {
throw new CustomException("File not found: " + fileOriginNm);
}
try {
String mimeType = URLConnection.guessContentTypeFromName(file.getName()); // 파일 이름을 기반으로 MIME 타입(파일의 콘텐츠 유형)을 추정
if (mimeType == null) {
mimeType = "application/octet-stream";
}
response.setContentType(mimeType);
String encodedFileName = URLEncoder.encode(fileOriginNm, StandardCharsets.UTF_8).replaceAll("\\+", "%20"); // 한글명, 특수문자 인코딩
response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", encodedFileName));
response.setContentLength((int) file.length());
@Cleanup // InputStream, Reader와 같은 자원은 사용 후 반드시 닫아야 하는데, 이 과정을 Lombok으로 자동화
// InputStream - Java에서 데이터를 바이트 단위로 읽어들이기 위한 최상위 추상 클래스(FileInputStream를 통해 구현). 네트워크 소켓 등에서 데이터를 읽을 때 사용
// FileInputStream - 파일로부터 바이트 스트림을 읽어 파일을 열고, 그 내용을 InputStream을 통해 읽음
// BufferedInputStream - 작은 바이트 단위로 여러 번 읽는 대신, 버퍼(일정 크기의 메모리 공간)를 사용하여 한 번에 더 많은 데이터를 읽어 입출력 성능이 향상
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
// 파일이나 스트림 간의 복사를 간단하게 수행. copy(InputStream in, OutputStream out) 메서드는 주어진 입력 스트림(in)에서 데이터를 읽어, 주어진 출력 스트림(out)으로 데이터를 복사
FileCopyUtils.copy(inputStream, response.getOutputStream());
} catch (IOException e) {
throw new CustomException("File not found: " + fileOriginNm);
}
}
- 코드 실행 과정 -
- 파일 준비: uploadPath로 프로젝트 내 위치한 파일 경로를 가져와 파일 객체로 생성
- 응답 설정 세팅: response에 필요한 타입, 헤더 등을 설정
- FileInputStream을 통해 파일 열기: new FileInputStream(file)으로 파일을 열고, 이 파일에서 데이터를 읽어들일 수 있는 스트림(FileInputStream)을 생성
- BufferedInputStream을 통해 버퍼링: 파일로부터 읽는 스트림을 버퍼링하여 더 효율적으로 데이터를 읽을 수 있도록 구성
- @Cleanup을 사용해 자동으로 리소스 해제: @Cleanup 어노테이션으로 inputStream이 더 이상 사용되지 않을 때 자동으로 close() 메서드를 호출하여 스트림을 종료시킴
- 파일 데이터 전송: FileCopyUtils.copy(inputStream, response.getOutputStream())을 통해 파일로부터 읽은 데이터를 클라이언트에게 전송하는 HTTP 응답의 출력 스트림(response.getOutputStream())으로 복사
프론트 (Vue.js)
const downloadFile = async (fileOriginNm: string | null, policyFileNm: string | null, policyFlpth: string | null) => {
if (!fileOriginNm || !policyFileNm || !policyFlpth) return alert('다운로드할 파일 정보가 올바르지 않습니다.')
const params = {
fileOriginNm,
policyFileNm,
policyFlpth,
}
try {
const queryString = new URLSearchParams(params).toString()
const response = await instance.get(`/policy/downloadFile?${queryString}`, {
responseType: 'blob',
})
if (!response || !response.data) return alert('데이터가 올바르지 않습니다.')
const blob = new Blob([response.data])
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = fileOriginNm
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(url)
} catch (error) {
console.error('다운로드 중 오류 발생:', error)
alert('파일 다운로드 중 오류가 발생했습니다.')
}
}
ref를 활용할 수 있는 환경이라면 DOM메소드 댜산 ref를 활용해도 괜찮다.
'Java' 카테고리의 다른 글
[Spring Boot] S3 연결하기 (0) | 2024.03.29 |
---|---|
백엔드 성능 측정 (0) | 2024.03.28 |
[Spring Boot] 에러 핸들링 (1) | 2024.02.20 |
Junit5 (0) | 2024.02.17 |
스프링 부트 서버에 https 설정 (0) | 2024.01.23 |
Comments