multipart/form-data 파일 업로드

웹 어플리케이션에서 업로드 한 파일을 처리해야 하는 경우가 있는데, request 기본 객체가 제공하는 기능만으로는 업로드 한 파일을 처리할 수가 없다.

 

파일 전송 방식

- 일반 파라미터를 전송할 때 사용하는 인코딩과 파일을 업로드 할 때 사용하는 인코딩은 서루 다르다. HTTP의 데이터 전송 방식은 크게 GET 방식과 POST 방식이 존재하는데, 이 두 방식의 차이는 파아미터 데이터를 요청 URL로 전송하느냐 아니면 스트림 방식으로 전송하느냐의 차이다.

- 스트림 기반의 전송 방식인 POST 방식은 또 다시 다음의 두가지 인코딩 방식에 따라서 전송하는 데이터 형식이 달라진다.

* application/x-www-form-urlencoded

* multipart/form-data

- 파일을 업로드 하기 위해서는 multipart/form-data인코딩을 사용해야만 한다.

-----------------------------------------------------

<form action="..." method="post" enctype="multipart/form-data">

...

</form>

-----------------------------------------------------

- 일반적인 인코딩 방식과 multipart/form-data 인코딩 방식은 웹 서버에 데이터를 전송할 때 다른 형태로 전송한다.

 

multipart/form-data 예제

- 실행 화면(multipart_form.jsp)에서 전송 버튼을 클릭하면 multipart/form-data 인코딩을 이용해서 텍스트 데이터와 파일 데이터를 multipart_data.jsp로 전송한다. multipart_data.jsp는 전송 받은 데이터를 그대로 응답 데이터로 출력해서 실제로 어떤 데이터가 전송되는지 확인할 수도 있도록 하였다.

▲ multipart_form.jsp 화면 미리보기

 

더보기

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="multipart_data.jsp" method="post" enctype="multipart/form-data">
    text1 : <input type="text" name="text1"/><br/>
    file1 : <input type="file" name="file1"/><br/>
    file2 : <input type="file" name="file2"/><br/>
    <input type="submit" value="전송"/>
</form>
</body>
</html>

 

 

 

더보기

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<%@ page language="java" contentType="text/plain; charset=UTF-8" pageEncoding="UTF-8"%>
<%@page import="java.io.IOException"%>
<%@page import="java.io.InputStream"%>
<%@page trimDirectiveWhitespaces="true" %>
<%
    InputStream is = null;
    out.print("[");
    out.print(request.getContentType());
    out.println("]");
    
    try{
        is = request.getInputStream();
        int data = -1;
        while((data = is.read()) != -1){
            out.print((char)data);
        }
    } finally{
        if(is != null){
            try{
                is.close();
            } catch(IOException e){
                e.printStackTrace();
            }
        }
    }
%>

 

 

 

 

 

 

 

 

 

 

 

 

 

▲ 전송을 누른 후 결과 화면

- 실행 결과에서 업로드 한 파일의 이름뿐만 아니라 파일의 내용도 함께 전송된 것을 확인할 수 있다.

* 첫 번째 줄 : request.getContentType()메서드의 결과 화면이다. 이 결과에서 "boundary=" 부분은 각각의 파라미터를 분류할 때 사용되는 구분자를 나타낸다. 각각의 파라미터는 구분자를 통해서 분류된다.

* Content-Disposition은 전송하는 파라미터의 이름을 나타낸다.(파일의 경우 파일명도 포함한다.)

* Content-Type은 업로드 한 파라미터의 타입을 나타낸다.

* 이후 한 줄(\r\n)을 추가한 뒤 파라미터의 값을 전송한다. 파일의 경우는 파일의 내용을 전송한다.

- 업로드 된 파일 데이터 및 텍스트 파라미터를 처리하기 위해서는 위 그림과 같이 전송된 데이터를 알맞게 처리하면 된다.

- 서블릿 2.5버전까지는 개발자가 직접 multipart/form-data 방식을 처리하는 코드를 작성하거나 또는 Commons FileUpload API와 같은 라이브러리를 이용해서 파일 업로드를 처리해야 했다. 서블릿 3.0은 파일 업로드 부분에 대한 API를 추가함으로써 FileUpload API등을 사용하지 않고도 파일 업로드 처리를 할 수 있도록 했다.

 

서블릿 3.0의 파일 업로드 구현

1. HttpServletRequest의 gerPart() 메서드를 이용해서 업로드 데이터 접근

2. 서블릿이 multipart 데이터를 처리할 수 있도록 설정

* @MultipartConfig 애노테이션 사용

* web.xml에서 <multipart-config>태그 사용

 

HttpServletRequest의 gerPart() 메서드를 이용해서 업로드 데이터 접근 자세히

- multipart/form-data 형식으로 전송된 데이터는 request.getParameter()와 같은 메서드로는 접근 할 수 없으며, 서블릿 3.0에 새롭게 추가된 Part 인터페이스를 사용해서 접근해야한다.

1. HttpServletRequest.getContentType()을 이용해서 multipart/form-data인지 확인한다.

2. multipart/form-data인 경우

2-1. HttpServletRequest의 getParts()나 getPart(name) 메서드를 이용해서 Part를 구한다.

2-2. Part의 getContentType()이 "application/"으로 시작하면, 파일로 처리한다.

2-3. Part의 getContentType()이 "application/"으로 시작하지 않으면 파라미터로 처리한다.