개요
안녕하세요 빈코입니다. 오늘은 Java를 활용한 이미지 다운로드 기능에 대해 포스팅하려 합니다. 이미지 다운로드는 크게 2가지로 분류되는데, 이미지의 binary를 직접 DB에 등록하거나 또는 이미지의 파일명과 파일 경로만 DB에 저장한 후 해당 정보를 꺼내서 서버에 등록된 이미지를 찾는 방법이 있습니다. 실무에서는 DB 공간을 생각하여 binary를 직접 등록하지 않고, 서버에 저장하는 방식으로 많이 사용하기 때문에 이번 포스팅도 서버에서 찾아서 다운로드하는 방법을 포스팅하려 합니다. 자세한 방법은 하단에서 설명할게요😃
파일 Table & 조회 Query📙
CREATE TABLE file_info (
id INT AUTO_INCREMENT PRIMARY KEY,
file_name VARCHAR(255) NOT NULL,
file_path VARCHAR(255) NOT NULL
);
가장 먼저 해야할 일은 파일의 정보를 담을 테이블을 생성하는 것입니다. 간단한 예제이기 때문에 자동 증가하는 값인 파일 아이디(id), 파일명(file_name), 파일 경로(file_path)만 선언하였습니다. 3개의 칼럼 모두 필수값이기 때문에 NOT NULL 제약 조건을 걸었습니다.
<select id="getFileById" parameterType="int" resultType="map">
SELECT file_name, file_path
FROM file_info
WHERE id = #{id}
</select>
이후에는 파일 아이디 값을 이용하여 위에서 생성한 파일 테이블에서 파일 정보(파일명, 파일 경로)를 조회하는 쿼리를 작성했습니다. 파일 아이디는 테이블 생성 시 INT로 선언하였기 때문에, 통일성을 위하여 parameterType도 int형으로 구성하였습니다.
jsp & js 설정📘
// jsp 버튼 설정
<button type="button" class="btn btn-default btn-xs" id="btnImgDownload" title="이미지 다운로드"><i class="glyphicon glyphicon-download"></i></button>
이후에는 사용자에게 보여질 UI를 구성합니다. 위치적인 부분은 생략하고 버튼을 생성 후 해당 버튼에 위 이미지처럼 CSS를 입힌 다음에 js에서 활용하기 위하여 id="btnImgDownload" 값을 부여했습니다.
// 다운로드 버튼 클릭 시 이벤트
$('#btnImgDownload').click( function () {
var params = {"id":1};
formSubmit("file/download/image",params);
});
js에서는 jsp에 등록 된 id를 찾아서 click 이벤트로 구성했습니다.(jsp에서 onclick 이벤트를 사용해도 무관합니다)
Java 단으로 넘길 params에는 임의의 파일 아이디 값 1을 넘겼고, formSubmit을 활용하여 Java 단을 호출합니다.
Java 설정📒
@Service
public class FileService {
@Autowired
private FileMapper fileMapper;
public Map<String, String> getFileById(int id) {
return fileMapper.getFileById(id);
}
}
Service 클래스는 FileService로 작명하였고, 위에서 구성한 쿼리를 호출하였습니다. 여기서 전달받은 int형 id를 그대로 넘겨주었고, 쿼리의 리턴 값은 Map<String, String> 이기 때문에 위 코드처럼 구성하였습니다.
@PostMapping("file/download/image")
public void downloadFile(int id, HttpServletResponse response) throws IOException {
// 파일 정보 조회
Map<String, String> fileInfo = fileService.getFileById(id);
if (fileInfo == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
String fileName = fileInfo.get("file_name");
String filePath = fileInfo.get("file_path");
// 파일 객체 생성
File file = new File(filePath);
if (!file.exists()) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
// 응답 헤더 설정
response.setContentType("image/png");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + ".png");
response.setContentLengthLong(file.length());
// 파일 전송
try (FileInputStream fis = new FileInputStream(file);
OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
}
}
downloadFile 함수에서는 js에서 넘겨받은 파일 아이디 값을 Service단으로 넘기고, 이후에 파일 정보(file_name, file_path)를 다시 전달받습니다. 그리고 해당 파일 경로에 파일을 찾는데, 여기서 만약 파일이 없을 경우에는 예외 처리를 진행하고 리턴합니다.
만약 파일이 있다면 응답 헤더를 설정하고 파일을 전송합니다. try-with-resources 구문은 자원은 자동으로 관리하기 위한 구문입니다. try 블록이 끝날 때 자원을 자동으로 닫아주는 역할을 합니다.
FileInputStream은 파일을 읽어들이기 위한 스트림이며, file은 다운로드할 파일 객체로, 해당 파일의 내용을 읽습니다. 읽은 후에는 클라이언트로 데이터 전송을 하는 OutputStream이라는 스트림을 이용하여 파일 다운로드를 진행합니다.
마치며
지금까지 이미지 파일 다운로드 기능에 대해 간단한 예시와 함께 설명드렸습니다. 정말 작은 기능이지만, 프런트 단에서 백엔드까지 전반적으로 손을 봐줘야 하고, 특히 예외 처리 등 신경 써야 하는 부분들이 있어서 처음 접한다면 다소 까다로울 수도 있을 것 같네요. 다음 포스팅에서 더 유익한 정보로 찾아뵐게요😁
'TIL' 카테고리의 다른 글
Java 파일 다운로드 OutOfMemoryError 해결방법(전체 예시) (0) | 2025.01.11 |
---|---|
Java 파일 다운로드 OutOfMemoryError 해결방법(예시) (0) | 2024.12.31 |
js 드래그 앤 드롭(drag&drop) 사용하기 (0) | 2024.12.18 |
Java Integer와 int 차이로 인한 오류 방지 (실무 예제) (2) | 2024.12.14 |
PostgerSQL Upsert 쿼리 개념 및 대용량 속도 차이 예제 (0) | 2024.11.23 |