[Java] Servlet 환경 - 파일 업로드(프로그래스바로 파일 업로드 상태를 표시하는 방법)


Development note/Java  2019. 10. 27. 09:00

안녕하세요. 명월입니다.

 

이 글은 [Java] Servlet 환경 - 파일 업로드(프로그래스바로 파일 업로드 상태를 표시하는 방법)에 대한 글입니다.

 

이전에 제가 PHP환경에서 ajaxForm을 이용해서 파일 업로드할 때 프로그래스바가 표시되게 끔 설명한 적이 있습니다.

링크 - [PHP] ajaxForm을 이용한 파일 업로드(프로그래스바로 파일 업로드 상태를 표시하는 방법)

 

사실 이 부분은 저 PHP로 작성한 html은 같습니다만, 서버사이드가 다릅니다. 그냥 파일 업로드하는 설정에 대한 설명이라고 보시면 됩니다.

링크 - [Java강좌 - 40] Java에서 웹 서비스 프로젝트(Jsp servlet)를 작성하는 방법

 

먼저 Servlet환경을 구축하고 index.jsp파일을 만들겠습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
  <title>title</title>
  <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
</head>
<body>
  <form enctype="multipart/form-data">
    <input type="file" name="data">
    <input type="submit">
  </form>
  <br />
  <br />
  <div class="progress-label"></div>
  <div id="progressbar"></div>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.2.2/jquery.form.min.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
  <script>
    $(function() {
      var progressbar = $("#progressbar");
      var progressLabel = $(".progress-label");
      progressbar.progressbar({
        value: true,
        change: function() {
          progressLabel.text("Current Progress: " + progressbar.progressbar("value") + "%");
        },
        complete: function() {
          progressLabel.text("Complete!");
          $(".ui-dialog button").last().trigger("focus");
        }
      });
      $('form').ajaxForm({
        url: "upload",
        type: "POST",
        beforeSubmit: function(arr, $form, options) { 
          progressbar.progressbar( "value", 0 );
        },
        uploadProgress: function(event, position, total, percentComplete) {
          progressbar.progressbar( "value", percentComplete );
        },
        success: function(text, status, xhr, element) {
          progressbar.progressbar( "value", 100 );
        }
      });
    });
  </script>
</body>
</html>

이 소스는 위에서 PHP환경에서 작성한 것이랑 같습니다. 그냥 url부분에서 저는 localhost/upload 의 경로로 파일을 업로드 할 것입니다.

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

@MultipartConfig
// 업로드 url은 localhost/uplaod이다
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public UploadServlet() {
    super();
  }

  // 파일업로드는 post형식으로 바운더리로 요청이 오기 때문에 doGet은 필요가 없겠네요.
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 해더의 바운더리 영역을 취득한다.
    Collection<Part> parts = request.getParts();
    // 해더 영역을 전부 for문으로 탐색한다.
    for (Part part : parts) {
      // 파일 관계된 바운더리 데이터가 아니면 패스
      if (!part.getHeader("Content-Disposition").contains("filename=")) {
        continue;
      }
      // 해더 바운더리 영역에서 파일 이름을 추출한다.
      String fileName = extractFileName(part.getHeader("Content-Disposition"));
      // 파일 이름이 null이 아니거나 사이즈가 0보다 크면..
      if (fileName != null && part.getSize() > 0) {
        // 저는 임의의 d:\\work 폴더에 업로드 하겠습니다.
        part.write("d:\\work\\" + File.separator + fileName);
        part.delete();
      }
    }
  }
  // 바운더리 헤더에서 파일 이름을 추출하는 함수
  private String extractFileName(String partHeader) {
    // 바운더리의 해더는 ;의 구분으로 데이터가 있다.
    for (String cd : partHeader.split(";")) {
      // 헤더 이름이 filename으로 시작하는 것이라면
      if (cd.trim().startsWith("filename")) {
        // '='무터 끝까지 따옴표는 제거
        String fileName = cd.substring(cd.indexOf("=") + 1).trim().replace("\"", "");
        // 그리고 디렉토리 표시 된것도 제거
        int index = fileName.lastIndexOf(File.separator);
        // 파일 이름 추출
        return fileName.substring(index + 1);
      }
    }
    // 위 조건에 맞지 않으면 null 리턴
    return null;
  }
}

다음은 업로드 용량에 관한 xml 설정입니다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://java.sun.com/xml/ns/javaee"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">
  <display-name>FileUpload</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>FileUploadServlet</servlet-name>
    <servlet-class>servlet.FileUploadServlet</servlet-class>
    <multipart-config>
      <!-- 요청 사이즈 제한을 두지 않는다. -->
      <max-file-size>-1</max-file-size>
      <!-- 요청 사이즈 제한을 두지 않는다. -->
      <max-request-size>-1</max-request-size>
      <file-size-threshold>1024</file-size-threshold>
    </multipart-config>
  </servlet>
  <servlet-mapping>
    <servlet-name>FileUploadServlet</servlet-name>
    <url-pattern>/upload</url-pattern>
  </servlet-mapping>
</web-app>

참조 - https://dololak.tistory.com/726

 

제가 구현하기 조금 귀찮아서 도로락님 블로그를 참조했습니다. 아주 잘 구현되서 좀 더 응용하시려면 위 참조 링크를 확인하세요.

 

이제 프로그램을 기동하고 업로드를 하겠습니다.

업로드 전의 이미지입니다. 파일은 150메가 정도 크기의 바이너리 데이터입니다.

업로드를 시작하겠습니다.

지정된 d:\work 드라이브에 파일이 잘 저장되었습니다.

 

여기까지 [Java] Servlet 환경 - 파일 업로드(프로그래스바로 파일 업로드 상태를 표시하는 방법)에 대한 설명이었습니다.

 

궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.