일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 기술 대비
- Model1
- AOP
- MVC
- 인프런
- 스프링
- @RestController
- 자바
- 코테
- @Controller
- MVC2
- SQL
- 메이븐
- STS
- order by
- select
- 서브쿼리
- DDL
- Model2
- 세션
- 코딩테스트
- JSP
- 김영한
- toUpperCase
- 프레임워크
- Join
- 인텔리제이
- 뉴렉처
- 프로그래머스
- 서블릿
- Today
- Total
Heestory
파일 다운로드: POST 방식과 location.href의 차이점과 구현 방법 본문
웹 개발 중 사용자에게 파일을 다운로드하도록 제공해야 하는 경우가 많습니다. 제가 이번 프로젝트에서 똑같은 파일 다운로드였으나 어떤 곳에선 되고, 어떤 곳에선 안되는 문제가 발생했었고, 1차적으로 POST방식을 썼기 때문에 다운로드가 부분적으로만 가능했었습니다.
이번 글에서는 POST 방식과 location.href를 이용한 파일 다운로드 방식의 차이점을 설명하고, 파일 다운로드를 구현하는 Java 컨트롤러 코드를 분석해 보겠습니다.
1. POST 방식 vs. GET 방식(location.href)
POST 방식의 파일 다운로드
POST 방식으로 파일 다운로드를 구현하려면, 서버에서 파일을 처리하고 응답으로 파일 데이터를 전송해야 합니다. 일반적으로 POST 방식은 데이터를 서버로 전달하는데 사용되며, 파일 다운로드 시에는 다음과 같은 특징이 있습니다:
- 장점:
- 요청 데이터와 함께 서버에서 다양한 처리를 수행 가능.
- 보안 측면에서 요청 데이터가 URL에 노출되지 않음.
- 단점:
- 브라우저 호환성 문제가 발생할 수 있음.
- 모바일 환경에서 일부 브라우저가 POST 요청 후 파일 응답을 처리하지 못하는 경우가 있음.
function downloadFileWithPost() {
// 동적으로 form 생성
const form = document.createElement("form");
form.method = "POST";
form.action = "/download/file";
document.body.appendChild(form);
form.submit(); // 폼 제출
document.body.removeChild(form); // 폼 제거
}
GET 방식의 파일 다운로드(location.href)
GET 방식은 브라우저의 기본적인 요청 방식으로, URL만 지정해도 파일 다운로드가 가능합니다. JavaScript의 location.href를 통해 파일 다운로드를 요청하면 브라우저가 파일을 쉽게 처리합니다.
- 장점:
- 브라우저 호환성이 뛰어남.
- 간단하고 빠른 구현이 가능.
- 단점:
- 요청 데이터(URL 파라미터)가 노출될 수 있음.
function downloadFileWithGet() {
// 서버 컨트롤러 URL
const fileUrl = "/download/file?fileId=12345"; // 서버로 전달할 파라미터 포함
window.location.href = fileUrl; // GET 요청
}
POST 방식은 잘 동작하지만, 모바일 환경에서 일부 브라우저가 POST 요청 후 파일 응답을 처리하지 못하는 문제가 발생할 수 있습니다. 이 문제는 location.href를 사용하는 GET 방식으로 전환하여 해결할 수 있습니다.
2. 파일 다운로드 Java 컨트롤러 코드 분석
아래 코드는 POST 방식으로 파일 다운로드를 처리하기 위한 Java 컨트롤러 코드입니다. 주요 로직을 단계별로 설명하겠습니다.
String fileName = fileDir.substring(fileDir.lastIndexOf("/") + 1);
request.setCharacterEncoding("UTF-8");
File file = new File(fileDir);
fileName = new String(fileName.getBytes("UTF-8"), "UTF-8");
1. 파일명 추출 및 인코딩
- fileDir에서 파일 이름을 추출합니다.
- request.setCharacterEncoding("UTF-8")로 요청의 인코딩 방식을 설정하여 한글 파일명 문제를 해결합니다.
String header = request.getHeader("User-Agent");
if (header.contains("MSIE") || header.contains("Trident")) {
fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ";");
} else {
fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
}
2. 브라우저 호환성 처리
- 사용자 에이전트(User-Agent)를 확인하여 Internet Explorer(IE)와 그 외 브라우저(Chrome, Firefox 등)를 구분합니다.
- IE는 URLEncoder.encode를 사용하여 파일명을 UTF-8로 인코딩하며, 다른 브라우저는 ISO-8859-1로 변환합니다.
int bytes = (int) file.length();
response.setContentType("application/octet-stream; UTF-8");
response.setContentLength(bytes);
response.setHeader("Content-Transfer-Encoding", "binary;");
response.setHeader("Pragma", "no-cache;");
response.setHeader("Expires", "-1;");
3. 응답 헤더 설정
- 파일 전송 타입을 application/octet-stream으로 설정하여 브라우저가 파일로 처리하도록 유도합니다.
- 캐싱을 방지하기 위해 Pragma와 Expires 헤더를 설정합니다.
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
byte[] readByte = new byte[4096];
try {
while ((bytes = bis.read(readByte)) > 0) {
bos.write(readByte, 0, bytes);
}
bos.flush();
} catch (Exception e) {
logger.error("EdocController.fileDownload Exception! : {}", e.getMessage());
} finally {
bos.close();
bis.close();
}
4. 파일 스트림 처리
- 파일 데이터를 읽고(BufferedInputStream) 클라이언트로 전송합니다(BufferedOutputStream).
- 4KB 버퍼(byte[4096])를 사용하여 효율적으로 파일을 전송합니다.
- 예외 처리와 자원 해제를 통해 안정성을 확보합니다.
저의 경우 GET방식으로 바꿔서 진행했을 때 ios와 android 둘 다 안되는 것이 android만 되는 문제가 생겨 브라우저마다 인코딩을 다르게 파일 다운로드를 하니 둘 다 다운로드가 잘 되었습니다. 혹시 다운로드 코드를 작성하고도 안된ㄷ면 핸드폰 내 캐시를 제거하고 진행해보는 것도 좋겠습니다
'개발(0) > Java' 카테고리의 다른 글
세션(Session)과 쿠키(Cookie)의 차이점과 사용 사례 (0) | 2025.01.16 |
---|---|
동일 Host에서 다른 포트의 두 프로젝트 간 POST 요청 시 세션 충돌 문제 해결 방법 도메인 변경 (0) | 2025.01.13 |
[IntellJ]자바 프로젝트 중 빌드가 되지 않을 때 (0) | 2024.05.07 |
[코드 개선]파라미터가 많을 때 (0) | 2023.08.17 |