Programming/Java

(java) 어플리케이션 단계에서 외부 이미지 파일 불러오는 방법

Jan92 2023. 3. 1. 22:50
반응형

java, application 단계에서 외부 이미지 파일 불러오는 방법

 

java 이미지 파일 가져오는 방법

 

어플리케이션에서 파일 업로드를 구현할 때, 업로드되는 파일의 경우 application 내부의 static 폴더에 저장되는 것이 아니라 application 외부에 있는 서버 단의 별도의 공간에 저장되거나, 외부 파일 서버에 저장되는 방식이 사용되는데요.

 

업로드 이후 해당 이미지 파일을 보기 위해서는 web server를 통한 방식이 주로 사용됩니다.

하지만 특수한 경우로 web server를 통해 정적 파일에 접근하는 것이 아니라, 어플리케이션 단계에서 해당 파일을 가져와야 하는 경우가 있는데요. 이때 어떤 방법으로 application 단계에서 이미지 파일을 가져올 수 있는지 살펴보겠습니다.

 

 


핵심이 되는 부분

@GetMapping("/get")
public void get(HttpServletResponse response) throws IOException {

    ServletOutputStream outputStream = response.getOutputStream();
    
    File file = new File("/home/image/test.jpg");
    if (!file.exists()) {
        //해당 파일이 존재하지 않을 때 처리
    }
    FileInputStream inputStream = new FileInputStream(file);

    int length;
    byte[] buffer = new byte[1024];

    while ((length = inputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, length);
    }
}

application 단계에서 외부 이미지 파일을 가져오는 코드의 핵심이 되는 부분입니다.

 

핵심은 간단한데, 파일이 저장된 물리적인 경로를 통해 File 객체를 생성하고, 해당 File을 InputStream 형식으로 만들어 HttpServletResponse를 통해 가져온 OutputStream을 통해 출력하는 것인데요.

 

 

여기서 한 가지 주목해 볼 수 있는 부분은 byte 배열로 된 'buffer의 크기'입니다.

어떤 코드에서는 byte 배열의 크기가 10으로 작은 것도 있고, 다른 코드 예시에서는 byte 배열의 크기가 4096처럼 큰 것도 있는데요.

 

이 부분에 대해 스트리밍 서비스를 예로 들어 간략하게 설명하자면,

여기서 버퍼의 크기는 한 번에 데이터를 받아오는 단위로 볼 수 있습니다. 버퍼가 커지면, 즉 한 번에 데이터를 받아오는 단위가 커지면 반응 속도가 느려집니다. 정해진 크기의 버퍼를 다 채워야 해당 데이터를 전송할 것이기 때문에 버퍼의 크기가 커지면 보내는 시간도 길어지게 되는 것인데요.

반대로 버퍼를 작게 잡으면 데이터의 크기가 작기 때문에 보내는 시간은 줄어들지만, 해당 데이터를 받는 시스템에서의 처리가 바빠지게 됩니다.

때문에 버퍼의 크기는 사용 중인 시스템에 따라 적절한 값이 다를 수 있으며, 시스템에 무리가 가지 않는 선에서 작게 잡아주는 것이 좋습니다.

 

(핵심만 살펴보기 위해 Controller 단에 내용을 바로 넣었으며, 예외처리 등을 하지 않았다는 점 참고 부탁드립니다.)

 

 

 

***

실제로 해당 코드가 사용되는 부분에서는 파일을 업로드할 때 해당 파일이 저장되는 경로 및 파일 명, 확장자를 모두 저장해 두고, 해당 파일의 고유값 등을 통해 요청되는 파일의 경로를 가져오는 로직이 추가될 수 있습니다.

 

또한 같은 서버 내에 파일이 있는 것이 아니라 파일이 완전히 외부 서버에 있는 경우에는 ftp, sftp 등을 이용할 수 있는데요.

 

try {
    if (exists(path)) {
        try (InputStream inputStream = channelSftp.get(path); OutputStream outputStream = servletOutputStream) {
            int length;
            byte[] buffer = new byte[1024];
            while ((length = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
            }
        } catch (SftpException e) {
            log.error("SFTP:: get image failed.");
            e.printStackTrace();
        } catch (IOException e) {
            log.error("SFTP:: get image failed.");
            e.printStackTrace();
        }
    }
}

'sftp'의 경우 다음과 같이 ChannelSftp 인스턴스의 get() 메서드를 통해 해당 파일의 inputStream을 가져와 출력할 수 있으며,

(sftp에서 파일이 존재하는지 확인하는 exists 메서드의 경우 따로 구현된 것으로 필요하신 경우 포스팅 하단 github 코드를 참고하시면 됩니다.)

 

try (OutputStream outputStream = servletOutputStream) {
    inputStream = ftp.retrieveFileStream(path);
    //해당 경로에 파일이 있는지 체크
    if (inputStream == null) {
        throw new IOException("file not found.");
    }

    int length;
    byte[] buffer = new byte[1024];
    while ((length = inputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, length);
    }
}

'ftp'의 경우 FTPClient 인스턴스의 retrieveFileStream() 메서드를 통해 해당 파일의 inputStream을 가져와 출력할 수 있습니다.

 

 

 

< ftp, stp 관련 포스팅 >

2023.02.13 - [Programming/Java] - Java FTPClient를 통한 ftp 파일 업로드 내용 정리

2023.02.18 - [Programming/Java] - JSch를 이용한 java sftp 파일 업로드 구현

 

 

< ftp, sftp 구현 코드 주소 >

https://github.com/JianChoi-Kor/ttotw/tree/master/core-module/src/main/java/com/project/ttotw/lib

 

 

< 참고 자료 >

https://djusti.tistory.com/2

https://milkye.tistory.com/357

반응형