자바
파일 다운로드 try catch 시 자원 반납, exception 시 json 응답
Hyeongjun_Ham
2024. 12. 4. 13:42
이번에 많은 테스트를 하며 기록해 두면 좋을 것 같은 내용이다.
상황은 다음과 같다.
1. 파일 다운로드를 모두 void로 리턴한다.
- 스트림으로 이미 내보내서 커밋 됐는데 또 json으로 리턴하려고 하니 response has already been committed 에러가 나는 것으로 보임
2. 파일 다운로드 중간에 IOException 이 발생한 경우 json으로 응답하려고 함
크게 이 두가지다.
바로 코드로 들어가자
public void fileDownload(){
// ...
setDownloadResponseHeaders(...);
OutputStream outputStream = response.getOutputStream();
try (FileInputStream fileInputStream = new FileInputStream(downloadFile.toFile())) {
FileCopyUtils.copy(fileInputStream, outputStream);
} catch (IOException cae) {
cae.printStackTrace();
ErrorResponse.sendJsonResponse(response, ErrorCode.SERVER_ERR);
} finally {
outputStream.close();
}
}
- setDownloadResponseheaders()는 파일 다운로드를 위한 헤더 설정이다.
여기서 outputStream을 왜 try catch resource 구문을 활용하여 ( ) 안에 넣지않고 밖에 넣을 수 밖에 없었는지 실험을 많이 했다.
- ( ) 안에 outputStream이 있으면
1. copy부분에서 IOException이 발생한 경우 outputStream 자원이 먼저 반납된다.
2. 그런데 close 하기 전 commit을 하고 자원이 close 된다.
3. 그래서 ErrorResponse.sendJsonResponse() 메서드에서 응답을 생성 할 수 없다.
그래서 finally로 close 시켜줘야 commit을 내가 원하는 시점에 하고 close 할 수 있다.
아래는 json으로 응답하기 위한 메서드
public static void sendJsonResponse(HttpServletResponse response, ErrorCode errorCode) throws IOException {
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
try (OutputStream outputStream = response.getOutputStream()) {
ObjectMapper objectMapper = new ObjectMapper();
ResultVO resultVO = APIUtil.resResult(errorCode.getErrorCode(), errorCode.getErrorMsg(), null);
String json = objectMapper.writeValueAsString(resultVO);
outputStream.write(json.getBytes(StandardCharsets.UTF_8));
outputStream.flush();
}
}
여기서는 자원을 반납한다.