본문 바로가기
Java

[펌] JSP 에서의 파일 업로드

by 사우람 2010. 7. 12.

              JSP 에서의 파일 업로드

작성자 : (tornado@dolpung.pe.kr)

 

파일을 업로드 한다는 것은 원격의 사용자가 서버 측으로 네트워크를 통해 파일을 전송하는 일이다

보통 WEB 환경에서 사용자의 입력 값을 다른 페이지로 이동시키기 위해서는 Form 통한 데이터 전송을 하게 된다.

간단하게 사용자의 이름을 입력 받고 내용을 JSP 페이지나 기타 파일로 전송을 해야 때는 아래와 같은 HTML 폼이 작성이 되어야 것이다.

 

<Form action=receive.jsp Method=POST>

이름 : <Input type=TEXT name=userName> <BR>

<input type=SUBMIT value= >

</Form>

<@NHN@LINEBREAKER@NHN@>
위의 파일을 실행하면 Action 태그에 정의된 페이지에서 사용자의 입력 값을 전송 받을 있게 된다. 하지만 File 경우는 그리 만만치 않다. 사용자가 입력하는 값은 Text 형태의 값이 대부분이고, 전송되는 File 형태는 Binary 타입이기 때문이다.

때문에 파일이 전송될 때에는 파일의 형태를 읽어 들일 있는 Servlet 또는 Java Bean 제작해야 한다.

 

아래는 파일전송을 위한 HTML 형태이다.

 

<!-- FileName : uploadForm.html  파일위치 c:\tomcat4/webapps/ROOT/uploadTest -->

<Form action=receive.jsp Method=POST enctype=multipart/form-data>

이름 : <Input type=TEXT name=userName> <BR>

파일 : <Input type=FILE name=userFile><BR>

<input type=SUBMIT value= >

</Form>

 

위의 파일을 보면 enctype 이라는 태그가 데이터를 전송하게 타입을 지정하는 부분이다.

아래쪽의 Input type=FILE 이라는 부분은 파일을 선택할 있는 창이 뜨게 되는 부분이다.

 

이렇게 전송되는 데이터를 receive.jsp 에서는 request 객체를 이용해서는 절대로 값을 가져오지 못한다.  Enctype 명시가 되면 넘어오는 파라메터들은 하나의 스트림을 통해 전송이 되게 된다. 그렇기 때문에 스트림으로 넘어오는 데이터를 각각의 구분자를 이용하여 짤라내야 한다.

그럼 데이터는 어떻게 받아낼까.

ServletRequest 인터페이스 에는 getInputStream() 이라는 메소드가 있다. 메소드는 클라이언트 측에서 전송되는 스트림을 서버측에서 받아줄 통로를 열어주는 메소드 이다. 위의 메소드를 통하여 사용자가 전송하는 스트림을 받아올 것이다.

아래는 데이터를 받아오는 receive.jsp 파일이다.

 

<%-- FileName : receive.jsp  SavePath : c:\tomcat4/webapps\ROOT\uploadTest --%>

<%@ page contentType=text/html; charset=euc-kr %>

<%@ page import=java.io.* %>

<%

         BufferedReader bufReader =

 new BufferedReader(new InputStreamReader(request.getInputStream()));

         String read = “”;

         while((read = bufReader.readLine()) != null){

                  out.print(read + <BR>);

}

bufReader.close();

%>

위의 파일을 해당 경로에 두고 브라우져에서 HTML 파일부터 실행 시키고 Text 형태의 파일을 전송해보자. JAVA SOURCE 파일도 괜찮다.   실행이 되었다면 아래와 같은 그림이 나오게 된다.

 

 

 

 

 

 

 

 

위의 그림을 자세히 보면 일정한 양식으로 입력 값이 전송된다는 것을 있다.

-----------------------------7d33d86502e0

위와 같은 부분을 Delimeter 라고 부른다 이렇게 넘어온 딜리미터를 이용하여 각각의 내용을 수동으로 잘라내야 한다.

처음 나오는 딜리미터 아래를 보면 Content-Desposition: form-data; name=userName  이라는 부분이 나오는 것을 있는데 이것은 HTML 에서 넘어오는 Form Data 구분해서 그에 상응하는 Parameter Name Parameter Value 나눠서 보여준다는 것을 있다.  물론 tornado 라는 것은 파라미터 값이 되겠다.

 

다시 딜리미터가 시작이 되고 아랫줄에 filename= 이라는 곳이 시작이 되는데 이곳부터 실제 파일이 시작이 되는 것이다. 현재 업로드 파일은 TEXT 형식이기 때문에 위와 같이 보여지지만 Binary 형태의 자료가 업로드가 된다면 이상한 문자들을 화면 가득 만날 것이다.

 

참고로 Binary 자료를 서버측에서 받으려 한다면 절대로 Reader 계열의 IO 클래스들을 사용해서는 안된다. Reader 계열 클래스 들은 문자를 읽어 들이는 스트림 이기 때문에 Binary 자료를 읽어 들이게 되면 제대로 업로드가 되리라는 보장이 없다.

 

위와 같이 복잡한 과정을 통해 업로드가 된다는 것을 알아보았다.

다시 한번 강조하지만 HTML Form 태그에 enctype 명시가 되면 절대로 Request 객체로 값을 받지 못한다는 것을 상기하기 바란다. 자료를 업로드 때에는 Method 속성이  POST 여야 한다는 것도 잊지 말자.(그렇다고 GET 방식은 절대로 못한다는 것은 아니다)

MultipartRequest 파일 업로드 하기

위와 같은 복잡한 과정을 거쳐 업로드를 하게 된다면 자바 IO 제대로 공부하지 않은 사람은 업로드 게시판은 절대 꿈도 것이다. 하지만 이렇게 복잡한 업로드를 간단히 해결해 주는 클래스들이 인터넷 상에 제공되고 있다.

우리가 사용할 MultipartRequest 라는 업로드 컴포넌트는 Oreilly 사에서 제공하는 컴포넌트이며 컴포넌트를 사용할 때에는 저작권이 따른다는 것을 알고 있기를 바란다.

또한 컴포넌트를 사용하려면 Oreilly 책을 구입해야 한다고 명시하고 있다.

 

위의 컴포넌트를 받으려면 아래의 웹사이트를 방문하여야 한다.

http://servlets.com/cos/index.html

 

위의 주소로 접속을 하고 화면을 아래로 스크롤 하게 되면 압축파일이 있는 표를 만나게 되는데

날짜를 확인하고 제일 최신 버전을 다운로드 받으면 된다.

참고로 현재 최신 버전은 2002 11 05 판이다.

 

cos-05Nov2002.zip 같은 파일을 찾았다면 다운로드를 하고 적당한 곳에 압축을 푼다.

압축을 풀면 아래와 같은 디렉토리가 생기게 된다.

 


 

 

디렉토리의 구조는 아래와 같다.

classes 디렉토리는  MultipartRequest 클래스 들이 위치한 디렉토리 이다.

Doc 디렉토리는 MultipartRequest API Document 들어있는 디렉토리 이다

Lib 디렉토리는 MultipartRequest 클래스들을 압축하여 놓은 Library 디렉토리이다.

Src 디렉토리는 Source 디렉토리 이다.

upload.war 파일은 아카이브 라는 형태의 파일로서 이것을 webapps 놓고 톰캣을 Restart 하게 되면 해당 war 파일이 압축이 풀리며 바로 사용 가능한 상태로 되는 파일형식이다. 파일을 이용하여 테스트를 있다.

 

Lib 디렉터리에 있는 cos.jar 이라는 파일을 톰캣 설치디렉토리의 common/lib 복사 한다. (c:/tomcat4/common/lib)

common/lib 위치 시켜야 하는데 이유는 톰캣이 처음 시작될 common/lib 있는 라이브러리를 읽어 들일 있게 해당 파일을 로딩하기 때문이다. JDBC 드라이버도 마찬가지로 이곳에 위치시켜야 한다.

Tomcat restart 하게 되면 cos.jar 파일에 들어있는 클래스들을 이용할 있게 된다.

 

본격적으로 업로드를 해보자.

 

위에서 작성한 receive.jsp 파일을 아래와 같이 작성한다.

<%-- FileName receive.jsp  SavePath c:/tomcat4/webapps/ROOT/uploadTest --%>

<%@ page contentType="text/html;charset=euc-kr" %>

<%@ page import="com.oreilly.servlet.MultipartRequest" %>

<%@ page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy" %>

<%@ page import="java.util.*" %>

<%@ page import="java.io.*" %>

 

<%

             String savePath="c:/tomcat4/webapps/ROOT/uploadTest";   // 저장할 디렉토리 (절대경로)

             int sizeLimit = 10 * 1024 * 1024 ;      // 파일업로드 용량 제한.. 10Mb

             try{

                           MultipartRequest multi = new MultipartRequest(request, savePath,

                                                                  sizeLimit,"euc-kr",new DefaultFileRenamePolicy());

                           String userName = multi.getParameter("userName");

                           String fileName= multi.getFilesystemName("userFile");

                           String originFileName = multi.getOriginalFileName("userFile");

 

                           if(fileName == null) { 

                                        out.print("파일이 업로드 되지 않았습니다!!");

                           } else {

                                        fileName=new String(fileName.getBytes("ISO-8859-1"),"euc-kr");

                                        out.print("User Name : " + multi.getParameter("userName") + "<BR>");

                                        out.print("getFilesystemName()  : " + fileName + "<BR>");

                                        out.print("getOriginalFileName() : " + originFileName +"<BR>");

                           } // end if

             } catch(Exception e) {

                           out.print(e.getMessage());

             }

%>

 

http://localhost:8080/uploadTest/uploadForm.html 부터 실행을 한다.

업로드 파일을 선택하고 전송 버튼을 누르게 되면 아래와 같은 그림이 나오게 된다.

 

 

 

 

  

 

다시 위의 과정을 반복해 본다. 아래와 같은 그림이 나온다.

 

 

 

 

 

이제 업로드 디렉터리를 보게 되면 아래와 같은 그림이 나오게 된다.

 

 

 

 

 

 

위의 결과치를 보게 되면 MultipartRequest 안에 들어있는 가지의 메소드의 용법을 있다.

String fileName= multi.getFilesystemName("userFile");

String originFileName = multi.getOriginalFileName("userFile");

 

getFilesystemName() 메소드는 서버측으로 실제 업로드 파일의 이름을 얻어오는 메소드 라는 것을 수가 있다.

getOriginalFileName() 메소드는 사용자가 업로드 실제 파일 이름을 얻어오는 메소드 이다.

그리고 중복 파일이 있을 경우에는 자동으로 파일이름 뒤에 중복된 숫자가 붙는다는 것을 있다.

이제 이렇게 업로드 파일의 이름을 데이터베이스에 입력을 하게 되면 자료실을 쉽게 구현 수가 있게 된다.

 

다음으로 알아볼 것은 업로드 파일의 사이즈를 알아내는 부분이다.

MultipartRequest 에는 파일의 사이즈를 반납해 주는 메소드는 없다. 하지만 File 객체 자체를 반납해 주는 메소드가 존재한다.

실제 파일객체를 받게 경우 File 객체에서 사용할 있는 모든 메소드를 사용할 있다는 장점이 있다.

파일의 사이즈는 아래와 같이 얻어오면 된다.

File f = multi.getFile("userFile");

같이 받아오면 된다.  이제 이렇게 받아온 파일을 통해 파일의 사이즈 각종 정보를 얻을 있게 된다.

 

 

아래의 코드를 receive.jsp 파일에 추가한다. 위치는 userFile 이름을 받아오는 아랫쪽에 위치 시키면 된다.

File f = multi.getFile(userFile);

int fileSize = (int)file.length();

out.print(<BR> 파일 사이즈 : + fileSize + <BR>);

사이즈가 출력이 되는 것을 있을 것이다. 참고로 int 형변환 하는 것은 File 객체의 length() 메소드의 반환값이 long 이기 때문에 형변환을 해준 것이다.

 

이제 여러 개의 파일을 업로드를 해보자. 이렇게 업로드 파일을 데이터 베이스의 테이블에 저장해 보도록 하자.

테이블의 구조는 아래와 같다. MySQL test 데이터베이스에 만들도록 하자.

 

Create table upTable(

             num int unsigned not null auto_increment primary key,

             name varchar(50) not null,

             subject varchar(200) not null,

             contents text not null,

             up1 varchar(50),

             up2 varchar(50),

             up3 varchar(50),

             size1 int,

             size2 int,

             size3 int,

);

 

먼저 파일을 선택할 있는 HTML 형식의 문서가 있어야 한다.

 

) multiUp.html 

<HTML>

<HEAD>

             <TITLE>JSP UPLOAD Test</TITLE>

<HEAD>

<BODY>

<FORM name="frm" method="POST" ACTION="multiUp.jsp" enctype="multipart/form-data">

<TABLE Border="1">

             <TR>

                           <TD>이름 <input type="text" name="userName"></td>

             </TR>

             <TR>

                           <TD>제목 <input type="text" name="subject" size=40></td>

             </TR>

             <TR>

                           <TD>내용<TextArea name="contents" rows="10" cols="60"></textArea></td>

             </TR>

             <TR>

                           <TD>파일 1  <input type="file" name="up1"> </TD>

             </TR>

             <TR>

                           <TD>파일 2  <input type="file" name="up2"> </TD>

             </TR>

             <TR>

                           <TD>파일 3  <input type="file" name="up3"> </TD>

             </TR>

             <TR>

                           <TD> <INPUT TYPE="SUBMIT" value=" "> </TD>

             </TR>

</TABLE>

</FORM>

</BODY>

</HTML>

 

위의 파일에서 주의 하여야 것은 enctype=multipart/form-data 부분이다. 다시 강조하지만 enctype 부분이 생략되면 업로드가 안된다는 것을 알고 있기 바란다.

이제 위의 HTML 폼에서 넘어가는 파일들과 파라메터들을 받아서 저장해줄 JSP 파일이 필요하다.

아래의 파일이 역할을 해주는 파일이다.

) multiUp.jsp

<%-- FileName : multiUp.jsp   savePath : c:/tomcat4/webapps/ROOT/uploadTest  --%>

<%@ page contentType="text/html; charset=euc-kr" %>

<%@ page import="com.oreilly.servlet.MultipartRequest" %>

<%@ page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy" %>

<%@ page import="java.util.*" %>

<%@ page import="java.sql.*" %>

<%@ page import="java.io.*" %>

 

<%

 

             String savePath = "c:/tomcat4/webapps/ROOT/uploadTest"; // 업로드 경로

             int sizeLimit = 5 * 1024 * 1024;

 

             MultipartRequest multi = new MultipartRequest(request, savePath, sizeLimit, new DefaultFileRenamePolicy());

             /*

                오라클의 경우 아래와 같이 MultipartRequest 생성자 호출시에 한글이라는 것을 명시해야 한글이 안깨진다.

                MultipartRequest multi =

                          new MultipartRequest(request, savePath, sizeLimit, "euc-kr", new DefaultFileRenamePolicy());

             */

            

             // 넘어오는 파라메터.

             String userName = multi.getParameter("userName");

             String subject = multi.getParameter("subject");

             String contents = multi.getParameter("contents");

            

             // 넘어오는 파일 이름

             String fileName1 = multi.getFilesystemName("up1");

             String fileName2 = multi.getFilesystemName("up2");

             String fileName3 = multi.getFilesystemName("up3");

 

             // 파일  사이즈 받기

             int size1 = (int)(new File(savePath + "/" + fileName1).length());

             int size2 = (int)(new File(savePath + "/" + fileName2).length());

             int size3 = (int)(new File(savePath + "/" + fileName3).length());

            

             // 데이터베이스 접속

             Class.forName("org.gjt.mm.mysql.Driver").newInstance();

             Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");

 

             String query = "insert into upTable values(null, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

             PreparedStatement pstmt = conn.prepareStatement(query);

             pstmt.setString(1, userName);

             pstmt.setString(2, subject);

             pstmt.setString(3, contents);

             pstmt.setString(4,  fileName1);

             pstmt.setString(5,  fileName2);

             pstmt.setString(6,  fileName3);

             pstmt.setInt(7, size1);

             pstmt.setInt(8, size2);

             pstmt.setInt(9, size3);

             int affectedRow = pstmt.executeUpdate();

 

             pstmt.close();

             conn.close();

 

             if(affectedRow != 1){

                           out.print("데이터 베이스 입력에 실패하였습니다");

                           // 입력에 실패하였다면 서버측에 업로드 파일을 삭제한다.

                           Enumeration enum = multi.getFileNames();

                           while(enum.hasMoreElements()){

                                        new File(savePath + "/" + multi.getFilesystemName((String)enum.nextElement())).delete();

                           }

             }else{

                           response.sendRedirect("upList.jsp");

             }

%>

 

위의 파일을 보게 되면 넘어오는 파라메터를 request 객체로 받지 않고 request MultipartRequest 매개변수로 넘겨준 MultipartRequest 인스턴스인 multi 받아낸다는 것을 있다.

특히 한글 파일이 업로드가 때에는 주의를 해야 한다. MultipartRequest 객체로 파일을 받아올 charset 지정되지 않으면 한글인 경우 파일이름이 깨지게 된다. 이때에는 주석 처리를 부분과 같이 한글문자셋을 지정해 줘야 한다.

하지만 MySQL 경우에는 한글인코딩을 하게 되면 한글이 다시 깨지게 되기 때문에 업로드 되는 파일의 이름만 부분적으로 한글 인코딩을 해줘야 하게 된다. 여러가지 시도를 해보고 각자의 환경에 맞게 고쳐서 쓰기 바란다.

 

파일의 사이즈를 받는 부분은 파일을 생성하고 그곳에 length() 메소드를 호출하여 int 형변환 하였다는 것을 있다.

반환값이 long 타입이기 때문에 형변환은 해줬지만 자신의 입맛에 맞게 사용하기 바란다.

 

앞서 했던 파일을 하나만 올리는 예제와 비교해 보면 이번 예제는 데이터베이스에 저장을 한다는 부분이 추가되었다.

데이터베이스에 저장할 때는 파일의 이름과 파일의 사이즈를 입력해주면 된다.

위에서 받아온 파일의 이름을 PreparedStatement IN 파라메터에 각각 대입을 해주고 executeUpdate 숫자를 받아주면 데이터베이스에 입력이 되었는가의 판단 여부를 알아 있다. 만약 데이터베이스에 입력이 되었다면 1 반환될 것이고 그렇지 않다면 0 반납이 되기 때문이다. 이렇게 나온 숫자를 이용하여 데이터 베이스에 입력이 안되었다면 기존의 업로드 파일들을 지워줘야 한다.

 

MultipartRequest 클래스의 메소드 중에는 파일입력 파라메터들의 이름을 Enumeration 객체로 반납해 주는 메소드가 있다.

바로 getFileNames() 라는 메소드 인데, 메소드가 해주는 역할은 파일이름을 반납하는 것이 아니라 파일이름이 담겨서 오는 파라메터들을 반납해 준다는 것이다. 이렇게 알아낸 파일들의 파라메터 이름들을 이용하여 getFilesystemName() 메소드에 알려주게 되면 실제 업로드 (중복파일이 있다면 변경된 이름을 반납) 파일의 이름을 알아 수가 있다.

이렇게 알게 파일의 실제 이름을 File 객체로 생성하여 delete() 메소드를 호출하게 되면 업로드 파일이 서버측에서 삭제되게 된다.

 

만약 데이터베이스에 입력이 되었다면 upList.jsp 파일로 요청이 넘어가게 되는데 upList.jsp 파일에서는 데이터베이스에 입력되어 있는 모든 레코드를 num 순서의 역방향(desc) 정렬하여 사용자 측에 보여주게 된다.

아래의 그림은 upList.jsp 파일이다. 제목을 클릭하면 업로드된 게시물의 내용과 업로드 파일을 수가 있다.

 

그림 . upList.jsp

 

 

 

 

                       

 

그럼 데이터 베이스에는 어떻게 들어가 있는지 보자.

MySQL 서버가 깔려있는 경로로 이동하여 mysql u root p test 라고 입력한 패스워드를 입력한다.

Select * from upTable; 같이 입력하면 아래와 같은 그림이 나오게 된다.

 

 

 

 

 

 

 

아래는 upList.jsp 파일의 소스이다.

예제 : upList.jsp

<%--  FileName upList.jsp    savePath=c:/tomcat4/webapps/ROOT/uploadTest  --%>

 

<%@ page contentType="text/html; charset=euc-kr" %>

<%@ page import="java.io.*" %>

<%@ page import="java.sql.*" %>

<%@ page import="java.util.*" %>

 

<%

             // 데이터베이스 접속

             Class.forName("org.gjt.mm.mysql.Driver").newInstance();

             Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");

 

             String query = "select * from uptable order by num desc";

             Statement stmt = conn.createStatement();

             ResultSet rs = stmt.executeQuery(query);

 

             out.print("<Table border=1>");

             out.print(" <tr>");

             out.print("              <td>번호</td>");

             out.print("              <td width=100>제목</td>");

             out.print(" </tr>");

 

             while(rs.next()){

               out.print("<tr>");

               out.print("  <td>"+rs.getInt("num")+"</td>");

               out.print("  <td><a href=upView.jsp?num="+rs.getInt("num")+">"+rs.getString("subject")+"</a></td>");

               out.print("            </tr>");

             }

             out.print("</table>");

 

             rs.close();

             stmt.close();

             conn.close();

%>

 

위에 있는 upList.jsp 그림과 같이 보인다면 제목을 클릭해 보자. upView.jsp 페이지가 이동되는 것을 있다.

이제 upView.jsp 에서 해야 일이 머릿속에 그려질 것이다.

먼저 해야 일은 upList.jsp  에서 넘어오는 파라메터의 값을 받아내야 한다.

num 값을 이용하여 쿼리를 전송하고 그렇게 얻어지는 결과치를 브라우져에 알맞게 뿌려주면 된다.

또한 파일들에 대하여 링크를 걸어줘야 파일을 클라이언트 측에서 인식을 수가 있게 된다.

현재는 파일에 대해 파일이름을 직접 지정하지만 추후 제작할 업로드 게시판에서는 다운로드를 해주는 파일을 제작할 것이다.

아래의 예제는 upView.jsp 파일이다. 파일이름에 대소문자 구별하여 저장한다.

 

예제 upView.jsp

<%-- FileName : upView.jsp   savePath : c:/tomcat4/webapps/ROOT/uploadTest --%>

<%@ page contentType="text/html; charset=euc-kr" %>

<%@ page import="java.sql.*" %>

<%

             int num = Integer.parseInt(request.getParameter("num"));

             // 데이터베이스 접속

             Class.forName("org.gjt.mm.mysql.Driver").newInstance();

             Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");

            

             String query = "select * from upTable where num="+num;

             Statement stmt = conn.createStatement();

             ResultSet rs = stmt.executeQuery(query);

            

             out.print("<table border=1>");

             if(rs.next()){

                           out.print("<tr>");

                           out.print(" <td>번호 : " + rs.getInt("num") + "</td>");

                           out.print(" <td colspan=2>제목 : " + rs.getString("subject") + "</td>");

                           out.print("</tr>");

                           out.print("<tr>");

                           out.print(" <td colspan=3>");

                           out.print("   파일 1 <a href=/uploadTest/"+rs.getString("up1")+">"+ rs.getString("up1") + "</a>");

                           out.print("  파일 2 <a href=/uploadTest/"+rs.getString("up2")+">"+ rs.getString("up2") + "</a>");

                           out.print("  파일 3 <a href=/uploadTest/"+rs.getString("up3")+">"+ rs.getString("up3") + "</a>");

                           out.print("</tr>");

                           out.print("<tr>");

                           out.print(" <td>내용</td>");

                           out.print(" <td colspan=2 height=50>" + rs.getString("contents") + "</td>");

                           out.print("</tr>");

                           out.print("<tr>");

                           out.print(" <td colspan=3>");

                           out.print("              <a href=modify.jsp?num="+rs.getInt("num")+">수정</a>");

                           out.print("              <a href=delete.jsp?num="+rs.getInt("num")+">삭제</a>");

                           out.print("</tr>");

             }

             out.print("</table>");

             rs.close();

             stmt.close();

             conn.close();

%>

 

위의 파일을 실행하면 아래와 같은 그림이 나오게 된다.

 

 

  

화면 하단에 보면 수정/삭제 부분이 보인다. 여기서 수정이란 기존의 파일을 삭제하고 새로운 파일을 올리겠다는 것이고

삭제는 기존의 파일과 데이터베이스에 들어있는 정보를 같이 삭제 하겠다는 것이다.

 

그럼 삭제를 먼저 해보자. 위의 그림에서 보이는 것과 같이 삭제 라는 곳에 마우스를 올리고 브라우져 하단에 나오는 링크정보를 보도록 하자 delete.jsp?num=1 같이 정보가 넘어가는 것을 있다.

delete.jsp  파일에서는 넘어오는 파라메터를 이용하여 데이터베이스에 쿼리를 하고 얻어진 파일이름을 이용하여 파일을 삭제하고 다시 데이터베이스의 레코드를 삭제하면 된다.  , 정보가 삭제되었다면 다시 upList.jsp 파일로 페이지를 이동시켜주면 된다.

아래의 예제를 작성한 실행 보고 윈도우탐색기에서 파일이 삭제 되었는지 보고, 데이터베이스에서는 레코드가 삭제 되었는지 확인해 보자.

 

예제. delete..jsp

<%-- FileName : delete.jsp   SavePath : c:/tomcat4/webapps/ROOT/uploadTest   --%>

<%@ page contentType="text/html; charset=euc-kr" %>

<%@ page import="java.sql.*" %>

<%@ page import="java.io.*" %>

<%

             int num = Integer.parseInt(request.getParameter("num"));

 

             String savePath = "c:/tomcat4/webapps/ROOT/uploadTest";

             String query1 = "select up1, up2, up3 from upTable where num="+num;

 

             Class.forName("org.gjt.mm.mysql.Driver").newInstance();

             Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");

             Statement stmt = conn.createStatement();

             ResultSet rs = stmt.executeQuery(query1);

             ResultSetMetaData rsmd = rs.getMetaData();

             int columnCount = rsmd.getColumnCount();

            

             if(rs.next()){

                           for(int i = 1; i <= columnCount; i++){

                                        if(rs.getString(i) != null || rs.getString(i).length() > 0){

                                                     new File(savePath + "/" + rs.getString(i)).delete();                                        

                                        }

                           }

             }

 

             String query2 = "delete from uptable where num="+num;

             stmt.executeUpdate(query2);

 

             rs.close();

             stmt.close();

             conn.close();

          response.sendRedirect(upList.jsp);

%>

 

위의 파일에서는 ResultSet 에서 나오는 테이블 정보를 이용하여(ResultSetMetaData) 선택된 컬럼의 개수를 알아내고, 그렇게 알아낸 컬럼의 숫자만큼 순환문을 돌면서 파일객체를 생성하여 업로드 파일을 삭제 하는 것을 있다.

이후 두번째 쿼리문 에서는 해당 레코드를 삭제하는 쿼리를 데이터베이스에 전송한 다는 것을 있다.

현재의 예제 파일에는 중간에 에러발생시 전혀 복구가 불가능한 상태인데 파일을 삭제 시에 정말 삭제 하는 것이 아니라 임시디렉토리를 하나 두고 삭제할 파일을 임시 디렉토리로 이동시킨후 해당 레코드가 정상적으로 삭제가 되었으면 임시디렉토리에 있는 파일을 실제로 삭제하는 방법을 써야 한다. 물론 업로드 때에도 위와 같은 방법을 쓰는 것이 좋다.

 

마지막으로 수정 하는 부분을 작성해 보도록 하자.

기존 업로드 파일들을 새로운 파일로 대치 하고, 내용에 대한 사항을 수정해야 하는 것이기 때문에 위의 delete.jsp 보다는 약간 복잡하다.

수정을 하려면 새로운 내용과 새로운 파일을 입력을 받을 있는 HTML 폼이 필요하다. 이곳에서 넘어가는 파라메터들에 대하여 작업을 해야 JSP 파일도 필요하다.

먼저 새로운 내용을 입력받는 형식을 작성해 보도록 하자.

 

예제. modify.jsp

<%-- FileName : modify.jsp   SavePath : c:/tomcat4/webapps/ROOT/uploadTest  --%>

<%@ page contentType="text/html; charset=euc-kr" %>

<%

             // 넘어오는 Number 값을 받아 Hidden 변수타입으로 넘겨준다.

             int num = Integer.parseInt(request.getParameter("num"));

%>

<HTML>

<HEAD>

             <TITLE>JSP UPLOAD Test</TITLE>

<HEAD>

<BODY>

<FORM name="frm" method="POST" ACTION="modifyUp.jsp" enctype="multipart/form-data">

<TABLE Border="1">

             <TR>

                           <TD>이름 <input type="text" name="userName"></td>

             </TR>

             <TR>

                           <TD>제목 <input type="text" name="subject" size=40></td>

             </TR>

             <TR>

                           <TD>내용<TextArea name="contents" rows="10" cols="60"></textArea></td>

             </TR>

             <TR>

                           <TD>파일 1  <input type="file" name="up1"> </TD>

             </TR>

             <TR>

                           <TD>파일 2  <input type="file" name="up2"> </TD>

             </TR>

             <TR>

                           <TD>파일 3  <input type="file" name="up3"> </TD>

             </TR>

             <TR>

                           <TD> <INPUT TYPE="SUBMIT" value=" "> </TD>

             </TR>

</TABLE>

<!-- 히든 변수로 modifyUp.jsp 파일에서 참조할 변수를 전달 한다 -->

<input type="hidden" name="num" value=<%= num %>>

</FORM>

</BODY>

</HTML>

 

modify.jsp 파일은 생각보다 상당히 단순하다. 그냥 HTML 입력폼 Hidden 변수타입만 추가된 형태이다.

이곳에서 hidden 변수를 modifyUp.jsp 파일에 반드시 넘겨줘야 한다. 그렇지 않으면 기존의 어느 레코드에 업데이트를 해야 수가 없기 때문이다. 이렇게 넘어간 num 변수 값과 새롭게 입력된 파라메터들을 modifyUp.jsp 파일에서 데이터 베이스 쪽으로 새롭게 갱신해 줘야 한다. 새롭게 넘어오는 파일이 있다면 해당 파라메터에 상응하는 컬럼이 가지고 있는 기존의 실제 파일을 삭제 해줘야 한다. 세곳의 파일 입력폼에서 전부 파일이 전송된다면 컬럼에 들어있는 파일정보를 이용하여 실제 파일을 삭제해야 하며 만약 한군데의 입력폼 에서만 파일이 전송된다면 해당되는 입력폼에 상응하는 컬럼이 가지고 있는 실제 파일을 삭제해 줘야 한다.

 

어렵겠지만 다음 장의 예제를 자세히 보자.

 

예제. modifyUp.jsp 

<%-- FileName : modifyUp.jsp   SavePath : c:/tomcat4/webapps/ROOT/uploadTest   --%>

 

<%@ page contentType="text/html; charset=euc-kr" %>

<%@ page import="com.oreilly.servlet.MultipartRequest" %>

<%@ page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy" %>

<%@ page import="java.util.*" %>

<%@ page import="java.sql.*" %>

<%@ page import="java.io.*" %>

<%

             String savePath = "c:/tomcat4/webapps/ROOT/uploadTest"; // 업로드 경로

             int sizeLimit = 10 * 1024 * 1024;

 

             MultipartRequest multi = new MultipartRequest(request, savePath, sizeLimit, new DefaultFileRenamePolicy());

 

             int num = Integer.parseInt(multi.getParameter("num"));

             String subject = multi.getParameter("subject");

             String contents = multi.getParameter("contents");

            

             boolean selectFlag = false;

             String selectQuery = "select ";

             String updateQuery = "update uptable set ";

             Enumeration e = multi.getFileNames();

             while(e.hasMoreElements()){

                           String formName = (String)e.nextElement();

                           if(multi.getFilesystemName(formName) != null){

                                        selectQuery += formName + ",";

                                        updateQuery += formName + "='" + multi.getFilesystemName(formName) + "',";

                                        selectFlag = true;

                           }

             }

            

             if(selectQuery.trim().endsWith(",")){

                           selectQuery = selectQuery.substring(0, selectQuery.length()-1);

             }

             selectQuery += " from upTable where num="+num;

             updateQuery += " subject='"+ subject + "', contents='"+contents+"' where num="+num;

 

//           out.print(selectQuery + "<BR>" + updateQuery);

             Class.forName("org.gjt.mm.mysql.Driver").newInstance();

             Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");

             Statement stmt = conn.createStatement();

             if(selectFlag){

                           ResultSet rs = stmt.executeQuery(selectQuery);

                           ResultSetMetaData rsmd = rs.getMetaData();

                           int columnCount = rsmd.getColumnCount();

                           if(rs.next()){

                                        for(int i = 1; i <= columnCount; i++){

                                                     new File(savePath + "/" + rs.getString(i)).delete();

                                        }

                           }

                           rs.close();

             }

             stmt.executeUpdate(updateQuery);       

             stmt.close();

             conn.close();

             response.sendRedirect("upList.jsp");

%>

 

위의 예제에서 보면 쿼리문장을 순환문을 통해 작성을 한다는 것을 수가 있다.

이는 사용자가 새로 갱신될 파일이나 내용을 어떻게 전송할 예측할 수가 없기 때문에 순환문을 통해 실제 업로드 파라메터에 해당하는 부분만 쿼리 문장에 포함을 시키려고 것이다.

위의 예제를 실행해 보면 실제 업로드 파일에 해당하는 부분의 컬럼 정보와 그곳에 저장되어있는 파일만 삭제 된다는 것을 있다. 어렵게 생각되는 예제 이지만 쇼핑몰의 상품 사진 업로드 부분을 작성하려면 위와 같은 방법을 응용해야 것이다.