1. 개요

웹 애플리케이션의 일반적인 기능은 파일을 다운로드하는 기능입니다.

이 사용방법(예제)에서는 다운로드 가능한 파일을 만들고 Java Servlet 애플리케이션에서 제공하는 간단한 예제를 다룰 것 입니다.

우리가 사용하고 있는 파일은 webapp 리소스에서 가져온 것입니다.

2. 메이븐 의존성

Jakarta EE를 사용하는 경우 의존성을 추가할 필요가 없습니다. 그러나 Java SE를 사용하는 경우 javax.servlet-api 의존성이 필요합니다.

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

의존성의 최신 버전은 여기 에서 찾을 수 있습니다 .

3. 서블릿

먼저 코드를 살펴보고 무슨 일이 일어나는지 알아봅시다.

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
    private final int ARBITARY_SIZE = 1048;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
      throws ServletException, IOException {
    
        resp.setContentType("text/plain");
        resp.setHeader("Content-disposition", "attachment; filename=sample.txt");

        try(InputStream in = req.getServletContext().getResourceAsStream("/WEB-INF/sample.txt");
          OutputStream out = resp.getOutputStream()) {

            byte[] buffer = new byte[ARBITARY_SIZE];
        
            int numBytesRead;
            while ((numBytesRead = in.read(buffer)) > 0) {
                out.write(buffer, 0, numBytesRead);
            }
        }
    }
}

3.1. Endpoints 요청

@WebServlet("/download") 어노테이션은 DownloadServlet 클래스가 "/download"  엔드포인트 로 향하는 요청을 처리하도록 표시합니다.

또는 web.xml 파일에서 매핑을 설명하여 이를 수행할 수 있습니다.

3.2. 응답 콘텐츠 유형

HttpServletResponse 개체 에는  HTTP 응답의 Content-Type 헤더 를 설정하는 데 사용할 수 있는 setContentType 이라는 메서드 가 있습니다.

Content-Type 은 헤더 속성의 이전 이름입니다. 또 다른 이름은 MIME 유형(Multipurpose Internet Mail Extensions)입니다. 이제 간단히 미디어 유형으로 값을 참조합니다.

이 값은 "application/pdf", "text/plain", "text/html", "image/jpg" 등 이 될 수 있습니다. 공식 List은 IANA(Internet Assigned Numbers Authority)에서 관리하며 여기 에서 찾을 수 있습니다. .

이 예에서는 간단한 텍스트 파일을 사용하고 있습니다. 텍스트 파일 의 Content-Type 은 "text/plain"입니다.

3.3. 응답 내용-처리

응답 객체에 Content-Disposition  헤더를 설정하면  브라우저가 액세스하는 파일을 처리하는 방법을 알 수 있습니다.

브라우저는 Content-Disposition 의 사용을 관례로 이해하지만 실제로는 HTTP 표준의 일부가 아닙니다. W3에는 여기 에서 읽을 수 있는 Content-Disposition 사용에 대한 메모가 있습니다 .

Response body의 Content-Disposition 값은 "인라인"(렌더링할 웹 페이지 콘텐츠의 경우) 또는 "첨부 파일"(다운로드 가능한 파일의 경우) 입니다 .

지정하지 않으면 기본 Content-Disposition 은 "인라인"입니다.

선택적 헤더 매개변수를 사용하여 파일 이름 "sample.txt"를 지정할 수 있습니다.

일부 브라우저는 지정된 파일 이름을 사용하여 파일을 즉시 다운로드하고 다른 브라우저는 사전 정의된 값이 포함된 다운로드 대화 상자를 표시합니다.

수행되는 정확한 조치는 브라우저에 따라 다릅니다.

3.4. 파일에서 읽기 및 출력 스트림에 쓰기

나머지 코드 줄에서는 요청에서 ServletContext 를 가져오고 "/WEB-INF/sample.txt"에서 파일을 가져오는 데 사용합니다.

HttpServletResponse # getOutputStream() 을 사용 하여 리소스의 입력 스트림에서 읽고 응답의 OutputStream 에 씁니다 .

우리가 사용하는 바이트 배열의 크기는 임의적입니다. InputStream 에서 OutputStream 으로 데이터를 전달하기 위해 할당하기에 합당한 메모리 양에 따라 크기를 결정할 수 있습니다 . 숫자가 작을수록 더 많은 루프가 있습니다. 숫자가 클수록 메모리 사용량이 많습니다.

이 주기는 파일의 끝을 나타내는 numByteRead 가 0이 될 때까지 계속됩니다.

3.5. 닫기 및 플러시

현재 보유하고 있는 리소스를 해제하려면 사용 후 스트림 인스턴스를 닫아야 합니다. 버퍼링된 나머지 바이트를 대상에 쓰려면 작성기 인스턴스도 플러시해야 합니다.

try-with-resources 문을 사용 하여 응용 프로그램은 try 문의 일부로 정의된 AutoCloseable 인스턴스 자동 으로 닫습니다 . try-with-resources에 대한 자세한 내용은 여기를 참조하십시오 .

우리는 이 두 가지 방법을 사용하여 메모리를 해제하고 준비한 데이터가 애플리케이션에서 전송되도록 합니다.

3.6. 파일 다운로드

모든 것이 준비되었으므로 이제 서블릿을 실행할 준비가 되었습니다.

이제 상대 Endpoints "/download" 를 방문하면 브라우저에서 파일을 "simple.txt"로 다운로드하려고 시도합니다.

4. 결론

서블릿에서 파일을 다운로드하는 것은 간단한 프로세스가 됩니다. 스트림을 사용하면 데이터를 바이트로 전달할 수 있으며 미디어 유형은 예상되는 데이터 유형을 클라이언트 브라우저에 알립니다.

응답을 처리하는 방법을 결정하는 것은 브라우저에 달려 있지만 Content-Disposition 헤더에 대한 몇 가지 지침을 제공할 수 있습니다.

이 기사의 모든 코드는 GitHub 에서 찾을 수 있습니다 .

res – REST with Spring (eBook) (everywhere)