웹에서 파일 업로드 구현-1 (jsp)
1. 환경설정
http://www.servlets.com/cos 에 접속한다.
위 그림 위치로 가서 .zip 파일을 다운받고 압축을 풀자.
(혹시 몰라 파일첨부)
lib폴더에 가면 cos.jar 파일이 있다. 편한 위치로 옮겨도 되고 그대로 써도 무방하다.
이 jar파일을 카피한 후
( 프로젝트 - WebContent - WEB-INF - lib ) 아래의 사진 위치에 붙여넣기한다.
그리고 데이터베이스 연동(오라클 사용)을 위한 ojdbc6.jar 와
jstl문 사용을 위한 jstl.jar & standard.jar 총 3개를 추가로 넣어준다.
ojbc6.jar의 기본경로는 C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib 이다.
(역시 귀찮은 분들을 위한 파일첨부)
jstl문을 위한 jar파일은 자바 JSTL 포스팅 에 업로드되어 있음.
2. 파일업로드 구축
파일업로드는 아래 사진과 같은 과정으로 이루어진다.
하나씩 단계별로 밟아갈 예정이다.
먼저 다음과 같은 간단한 폼을 위해 아래 html 코드를 추가한다.
Upload.html
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
<fieldset>
<legend>파일 업로드</legend>
<table>
<form action="UploadService">
<tr>
<td>글쓴이 : </td>
<td><input type="text" name="author"/></td>
</tr>
<tr>
<td>제목 : </td>
<td><input type="text" name="title"/></td>
</tr>
<tr>
<td>글쓴이 : </td>
<td><input type="file" value="파일 선택" name="file"/></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="업로드"/></td>
</tr>
</form>
</table>
</fieldset>
</body>
</html>
UploadService.java 서블릿을 만들어 값이 잘 들어오는지 확인한다.
UploadService.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/UploadService")
public class UploadService extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fileName = request.getParameter("file");
System.out.println(fileName);
}
}
토대.hwp
벌써 전송이 되었다고 생각할 수 있겠지만 파일을 전송하기 위해서는 GET방식이 아닌 POST방식으로 보내야 한다. Form태그에 method를 지정하지 않으면 기본 GET방식으로 설정되기 때문에 현재는 사실 파일이 업로드된 것이 아니고 토대.hwp 라는 텍스트만 전달된 것이다.
또 method="post"라고 전송방식만 바꿔준다고 해서 파일을 받아낼 수 있는 것은 아니다. 서버에 내가 파일을 보낼 것이라고 알려주기 위해 enctype 옵션에 'multipart/form-data'라고 선언해준다.
Upload.html의 <Form>태그를 다음과 같이 수정:
<form action="UploadService" method="post" enctype="multipart/form-data">
수정한 후 다시 한번 파일을 업로드하고 전송해봤을때
와 같이 null값이 뜨게 되면 잘 된 것이다.
그럼 실제로 서블릿에서 파일을 받아내기 위해서 아래 클래스의 메소드가 필요하다.
MultipartRequest 클래스의 메소드
UploadService.java 서블릿에 아래 MultipartRequest 객체를 생성한다.
밑의 표는 파라미터에 관한 설명이다.
MultipartRequest multi = new MultipartRequest(request, saveDir, maxSize, encoding, new DefaultFileRenamePolicy());
SerVletContext 인터페이스에 getServletContext() 메소드를 사용하면 현재 실행되는 어플리케이션에 대한 정보를 가져올 수 있다.
이 안에 들어있는 정보 중 우리가 필요한 경로를 구하기 위해 .getRealPath()를 이용하여 변수에 담아준다.
WebContent 안에 파일을 저장할 폴더를 만든 후 getRealPath()의 파라미터로 폴더이름을 주면 된다.
UploadService.java
ServletContext context = getServletContext(); //어플리케이션에 대한 정보를 ServletContext 객체가 갖게 됨.
String saveDir = context.getRealPath("Upload"); //절대경로를 가져옴
System.out.println("절대경로 >> " + saveDir);
Upload.html 을 실행시켜 파일을 업로드해보면
다음같은 경로가 나오게 된다.
절대경로 >> C:\Users\pc-20\Dropbox\JSP\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\FileUpload\Upload
위 경로를 탐색기로 실행하면 아래와 같이 메타데이터 안으로 들어가게 된다.
파일 max크기 설정. byte 단위로 설정되므로 계산을 통해 사용한다.
int maxsize = 3*1024*1024; // 3MB
인코딩 설정. 한글을 받기 위해 euc-kr로 설정한다.
String encoding = "euc-kr";
설정을 마치고 실제로 파일을 업로드해보면 아까 getRealPath()로 가져온 경로의 폴더에
파일이 업로드되어있음을 확인할 수 있고
같은 파일을 2번 업로드하면 숫자도 잘 붙음을 확인할 수 있다.
우리가 만든 Upload 폴더에는 실제로 파일이 들어있지 않아 헷갈리겠지만,
이미지 파일을 올리고 img태그로 확인해보면
test.html
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
<img src="Upload/images.jpg">
</body>
</html>
실제 Upload 파일에 들어있지 않지만 출력이 잘 됨을 확인할 수 있다.
그럼 이제 DB에 실제로 사용자가 입력한 정보와 파일정보를 업로드하기 위해
(이 과정)
DB에서 실제로 테이블을 만들고
create table fileboard(
num number,
author varchar(30),
title varchar(30),
fileName varchar(50),
day varchar(30)
);
순차적으로 증가하는 num을 위한 시퀀스 생성
//시퀀스 생성
create sequence file_num
start with 1
increment by 1;
테스트를 위해 SQL문으로 실제 삽입
insert into fileboard values(1, '도스토예프스키', '죄와 벌', 'file1', to_char(sysdate,'YYYY-MM-DD'));
DB구축이 끝났으면 연동을 위한 DAO클래스를 만들고 실제로 DB와 연동한다.(코드생략)
FileDAO.java
package com.Model;
public class FileDAO {
//DB연결
public void getConnection() {}
//DB연결 종료
public void close() {}
//파일업로드
public int uploadFile(String author, String title, String file) {
return 0;
}
}
ServletFileUploadisMultipartContent(request)를 사용하면 boolean 타입으로 넘어오는 Form태그의 전송방식을 확인할 수 있는데
boolean isMulti = ServletFileUpload.isMultipartContent(request);//boolean타입. ??????
if(isMulti) {
System.out.println("파일전송 Form입니다");
}else {
System.out.println("일반전송 Form입니다");
}
파일전송 Form입니다
위의 if-else 안에 FileDAO에 만들었던 insert SQL문을 실행하는 uploadFile()메소드를 UploadService 서블릿에 추가한다.
UploadService.java
boolean isMulti = ServletFileUpload.isMultipartContent(request);// boolean타입. ??????
if (isMulti) {
MultipartRequest multi = new MultipartRequest(request, saveDir, maxSize, encoding, new DefaultFileRenamePolicy());
FileDAO dao = new FileDAO();
String author = multi.getParameter("author");
String title = multi.getParameter("title");
String file = multi.getFilesystemName("file");
try {
int result = dao.uploadFile(author, title, file);
if (result > 0) {
System.out.println("저장완료");
} else {
System.out.println("저장실패");
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("일반 전송 Form입니다");
}
이제 Upload.html을 통해 파일을 업로드해보면
console에 저장완료가 뜨고 DB에 저장이 된 것을 확인할 수 있다.
이제 성공적으로 저장된 경우 SelectService.java로 이동하여 리스트를 검색하도록 할 것이다.
UploadService 서블릿에 아래 코드를 추가한다.
UploadService.java
boolean isMulti = ServletFileUpload.isMultipartContent(request);// boolean타입. ??????
if (isMulti) {
MultipartRequest multi = new MultipartRequest(request, saveDir, maxSize, encoding,
new DefaultFileRenamePolicy());
FileDAO dao = new FileDAO();
String author = multi.getParameter("author");
String title = multi.getParameter("title");
String file = multi.getFilesystemName("file");
try {
int result = dao.uploadFile(author, title, file);
String moveUrl = "";
if (result > 0) {
System.out.println("저장완료");
moveUrl = "selectService";
} else {
System.out.println("저장실패");
moveUrl = "Upload.html";
}
response.sendRedirect(moveUrl);
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("일반 전송 form 입니다.");
}
업로드가 성공하면 SelectService.java 서블릿으로 이동하게 되게 설정하였는데 아직 존재하지 않는 서블릿이므로 실제로 서블릿파일을 만든다.
이 SelectService.java는 DB에 저장된 file정보를 모두 검색해서 jsp로 전송하는 역할을 맡게 될 것이다.
SelectService.java
package com.Service;
import java.io.IOException;
import java.util.ArrayList;
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.Model.FileDAO;
@WebServlet("/selectService")
public class selectService extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//DB에 저장된 file정보를 모두 검색해서 jsp로 전송
FileDAO dao = new FileDAO();
//여러개니까 List로
ArrayList<FileVO> list = dao.selectAll();
}
}
FileVO와 FileDAO에 없는 selectAll 메소드에서 에러가 날 것이다.
먼저 ArrayList 제네릭에 들어가는 File정보를 받아줄 객체를 만들기 위한 클래스 FileVO.java를 만든다.
필드는 DB의 컬럼과 같다. 생성자와 getter메소드도 만든다.
FileVO.java
package com.Model;
public class FileVO {
private int num;
private String author;
private String title;
private String file;
private String day;
public FileVO(int num, String author, String title, String file, String day) {
this.num = num;
this.author = author;
this.title = title;
this.file = file;
this.day = day;
}
public int getNum() {
return num;
}
public String getAuthor() {
return author;
}
public String getTitle() {
return title;
}
public String getFile() {
return file;
}
public String getDay() {
return day;
}
}
FileDAO 클래스에 DB에 접속해 모든 정보를 읽어오는 selectAll()메소드를 만든다.
public ArrayList<FileVO> selectAll() {
//코드생략
return new ArrayList<FileVO>();
}
DB를 읽어오는 메소드가 완성되었으면 SelectService.java 서블릿으로 돌아와 다음과 같이 코드를 추가한다.
SelectService.java
package com.Service;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.RequestDispatcher;
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.Model.FileDAO;
import com.Model.FileVO;
@WebServlet("/selectService")
public class selectService extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//DB에 저장된 file정보를 모두 검색해서 jsp로 전송
FileDAO dao = new FileDAO();
try{
ArrayList<FileVO> list = dao.selectAll();
if(list!=null) {
request.setAttribute("list", list);
}else {
System.out.println("비었습니다");
}
RequestDispatcher dis = request.getRequestDispatcher("Board.jsp");
dis.forward(request, response);
}catch(Exception e) {
e.printStackTrace();
}
}
}
forward 방식으로 성공시 Board.jsp로 request, response 정보를 가지고 이동하게 되어 있다.
간단한 테스트를 위해 jsp페이지를 만들고 전송성공이라는 문구를 넣었다.
Board.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd";>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
전송성공
</body>
</html>
이제 Upload.html에서 다시 한번 파일을 업로드해본다.
DB에도 잘 올라가고
전송을 성공했으니 request, response 정보를 가지고 Board.jsp로 잘 넘어간 것을 확인할 수 있다.
(다음 포스팅에 계속)