자바

파일 다운로드 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();
        }
    }

 

여기서는 자원을 반납한다.