자바에서 파일을 업로드하기 위해서는 COS 라이브러리가 제일 많이 사용되고 있다. 참고로 COS는 com.oreilly.servlet의 약자이다. (tmi: O'reilly는 프로그래밍 책 출판으로 유명한 출판사 이름이자 CEO 이름.)
COS 라이브러리 준비
http://servlets.com/cos/ 에서 Download 항목을 찾아 다운받는다.
lib
폴더의cos.jar
파일을 새로 생성한 Dynamic Web Project의WEB-INF\lib
폴더에 복사한다.
폼 태그의 속성을
method="post",
enctype="multipart/form-data"
로 추가한다.
get방식은 주소창을 타고 넘어가기 때문에 255자 이하의 데이터만 전송할 수 있다. 따라서 파일과 같은 데이터는 post방식을 사용한다.
enctype 속성(인코딩 타입을 지정하는 속성)을 추가하지 않으면 파일 이름만 전송되고 파일 객체가 전송되지 않는다. 파일(이미지)이 전송된다고 알려주는 속성이라고 생각하면 된다.
참고 : 🔗 enctype이란?
type="file"로 지정한 input 태그를 form 태그 안에 추가해 파일 선택 버튼을 만들 수 있다.
파일 전송을 위해서는 type="submit"인 input 태그를 이용한다.
<%@ 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="upload.do" method="post" enctype="multipart/form-data">
글쓴이: <input type="text" name="name"><br>
제 목: <input type="text" name="title"><br>
파일 지정하기: <input type="file" name="uploadFile"><br>
<input type="submit" value="전송">
</form>
</body>
</html>
여기까지 입력하고 실행하면 파일 선택 버튼이 생성되고 전송할 파일을 선택할 수 있다.
실제 파일 전송을 위해서는 cos.jar파일에서 제공하는 MultipartRequest 클래스를 사용한다.
다음은 MultipartRequest의 생성자로, 생성되는 순간 파일이 전송되어 서버에 저장된다.
MultipartRequest(
javax.servlet.http.HttpServletRequest request,
java.lang.String saveDirectory,
int maxPostSize,
java.lang.String encoding,
FileRenamePolicy policy
)
new DefaultFileRenamePolicy()
를 사용한다.다음은 입력폼에서 선택한 파일을 실제로 업로드하는 서블릿 클래스다.
package com.saeyan.controller;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
@WebServlet("/upload.do")
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
// 여기를 바꿔주면 다운받는 경로가 바뀜
String savePath = "upload";
// 최대 업로드 파일 크기 5MB로 제한
int uploadFileSizeLimit = 5 * 1024 * 1024;
String encType = "UTF-8";
ServletContext context = getServletContext();
String uploadFilePath = context.getRealPath(savePath);
System.out.println("서버상의 실제 디렉토리 :");
System.out.println(uploadFilePath);
try {
MultipartRequest multi = new MultipartRequest(request, // request 객체
uploadFilePath, // 서버상의 실제 디렉토리
uploadFileSizeLimit, // 최대 업로드 파일 크기
encType, // 인코딩 방법
// 동일한 이름이 존재하면 새로운 이름이 부여됨
new DefaultFileRenamePolicy());
// 업로드된 파일의 이름 얻기
String fileName = multi.getFilesystemName("uploadFile");
if (fileName == null) { // 파일이 업로드 되지 않았을때
System.out.print("파일 업로드 되지 않았음");
} else { // 파일이 업로드 되었을때
out.println("<br> 글쓴이 : " + multi.getParameter("name"));
out.println("<br> 제 목 : " + multi.getParameter("title"));
out.println("<br> 파일명 : " + fileName);
}// else
} catch (Exception e) {
System.out.print("예외 발생 : " + e);
}// catch
}
}
MultipartRequest와, 파일 업로드시 중복 처리를 위한 DefaultFileRenamePolicy 클래스를 import한다.
파일은 savePath로 저장한 upload 폴더에 저장된다 (WebContent에 upload란 이름의 폴더 하나 만들자). 다음 코드로는 서버상에 파일이 저장되는 실제 경로를 찾아낸다.
ServletContext context = getServletContext();
String uploadFilePath = context.getRealPath(savePath);
C:\work\jspworkspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps
MultipartRequest multi = new MultipartRequest(
request, // request 객체
uploadFilePath, // 서버상의 실제 디렉토리
uploadFileSizeLimit, // 최대 업로드 파일 크기
encType, // 인코딩 방법
new DefaultFileRenamePolicy() // 동일한 이름이 존재하면 새로운 이름이 부여됨
);
파일 업로드와 관련한 요청 처리를 위해서는 MultipartRequest 클래스의 메소드를 사용해야 한다. 폼에서 전송된 파라미터의 이름을 얻기 위해서는 Request.getParameter()
를 사용할 수 없고 MultipartRequest.getParameter()
를 사용한다.
선택한 파일 이름을 얻어오려면 input태그의 name 속성 값을 getFilesystemName()
의 매개변수로 전달해준다. 업로드한 이름이 아니라 원래 파일명을 알고 싶으면 getOriginalFileName()
을 사용한다.