Programming/JSP2007/09/27 22:30

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

File을 Upload 한다는 것은 원격의 사용자가 Server 측으로 Network를 통해 File을 전송하는 일이다

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

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

<Form action=”receive.jsp” Method=”POST”>
이름 : <Input type=”TEXT” name=”userName”> <BR>
<input type=”SUBMIT” value=” 전 송 “>
</Form>

위의 File을 실행하면 Action Tag에 정의된 Page에서 사용자의 입력 값을 전송 받을 수 있게 된다. 하지만 File 의 경우는 그리 만만치 않다. 사용자가 입력하는 값은 Text 형태의 값이 대부분이고, 전송되는 File 의 형태는 Binary Type이기 때문이다. 이 때문에 File이 전송될 때에는 File의 형태를 읽어 들일 수 있는 Servlet 또는 Java Bean 을 제작해야 한다.

아래는 File 전송을 위한 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>

위의 File을 보면 enctype 이라는 Tag가 Data를 전송하게 될 Type을 지정하는 부분이다. 아래쪽의 Input type=”FILE” 이라는 부분은 File을 선택할 수 있는 창이 뜨게 되는 부분이다.

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

그럼 Data는 어떻게 받아낼까.

ServletRequest Interface에는 getInputStream()이라는 Method가 있다. 이 Method는 Client 측에서 전송되는 Stream을 Server 측에서 받아줄 통로를 열어주는 Method 이다. 위의 Method를 통하여 사용자가 전송하는 Stream을 받아올 것이다.

아래는 Data를 받아오는 receive.jsp File 이다.

<%-- 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();
%>

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



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

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

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

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

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

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

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

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

MultipartRequest  File Upload 하기

위와 같은 복잡한 과정을 거쳐 Upload를 하게 된다면 Java IO 를 제대로 공부하지 않은 사람은 Upload 게시판은 절대 꿈도 못 꿀 것이다. 하지만 이렇게 복잡한 Upload를 간단히 해결해 주는 Class들이 Internet 상에 제공되고 있다.

우리가 사용할 MultipartRequest 라는 Upload Component는 Oreilly 사에서 제공하는 Component이며 이 Component를 사용할 때에는 저작권이 따른다는 것을 알고 있기를 바란다.

또한 이 Component를 사용하려면 Oreilly 의 책을 구입해야 한다고 명시하고 있다. 위의 Component를 받으려면 Web Site를 방문하여야 한다.

위의 주소로 접속을 하고 화면을 아래로 Scroll 하게 되면 Archive File이 있는 표를 만나게 되는데 날짜를 확인하고 제일 최신 Version을 Download 받으면 된다.

cos-05Nov2002.zip 와 같은 File을 찾았다면 Download를 하고 적당한 곳에 압축을 푼다. 압축을 풀면 아래와 같은 Directory가 생기게 된다.



Directory의 구조는 아래와 같다.

- /classes : MultipartRequest의 Class들이 위치한 Directory 이다.
- /doc : MultipartRequest API Document 가 들어있는 Directory 이다.
- /lib : MultipartRequest의 Class들을 압축하여 놓은 Library Directory 이다.
- /src : Directory는 Source Directory 이다.

upload.war File은 Web Archive 라는 형태의 File로서 이것을 webapps 에 놓고 Tomcat을 Restart 하게 되면 해당 war File이 압축이 풀리며 바로 사용 가능한 상태로 되는 File 형식이다. 이 File을 이용하여 Test를 할 수 있다.

lib Directory에 있는 cos.jar 이라는 File을 Tomcat 설치 Directory의 common/lib에 복사한다. (c:/tomcat4/common/lib)

꼭 common/lib에 위치 시켜야 하는데 이유는 Tomcat이 처음 시작될 때 common/lib에 있는 Library를 읽어 들일 수 있게 해당 File을 Loading 하기 때문이다. JDBC Driver도 마찬가지로 이곳에 위치시켜야 한다. Tomcat 을 restart 하게 되면 cos.jar File에 들어있는 Class들을 이용할 수 있게 된다. 본격적으로 Upload를 해보자.

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

<%-- 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 부터 실행을 한다. Upload 할 File을 선택하고 전송 Button을 누르게 되면 아래와 같은 그림이 나오게 된다.



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



이제 Upload 된 Directory를 보게 되면 아래와 같은 그림이 나오게 된다



위의 결과치를 보게 되면 MultipartRequest 안에 들어있는 두 가지의 Method의 용법을 알 수 있다.

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

getFilesystemName() Method는 Server 측으로 실제 Upload 된 File의 이름을 얻어오는 Method 라는 것을 알 수가 있다.

getOriginalFileName() Method는 사용자가 Upload 한 실제 File 이름을 얻어오는 Method 이다.

그리고 중복 File이 있을 경우에는 자동으로 File 이름 뒤에 중복된 숫자가 붙는다는 것을 알 수 있다. 이제 이렇게 Upload 된 File의 이름을 Database에 입력을 하게 되면 자료실을 쉽게 구현 할 수가 있게 된다. 다음으로 알아볼 것은 Upload 된 File의 Size를 알아내는 부분이다.

MultipartRequest 에는 File의 Size를 반납해 주는 Method는 없다. 하지만 File 객체 자체를 반납해 주는 Method가 존재한다.

실제 File 객체를 받게 될 경우 File 객체에서 사용할 수 있는 모든 Method를 사용할 수 있다는 장점이 있다. File의 Size는 아래와 같이 얻어오면 된다.

File f = multi.getFile("userFile"); 과 같이 받아오면 된다. 이제 이렇게 받아온 File을 통해 File의 Size 및 각종 정보를 얻을 수 있게 된다. 아래의 Code를 receive.jsp File에 추가한다. 위치는 User File 이름을 받아오는 아랫쪽에 위치 시키면 된다.

File f = multi.getFile(“userFile”);
int fileSize = (int)file.length();
out.print(“<BR> 파일 사이즈 : “ + fileSize + “<BR>”);

Size가 잘 출력이 되는 것을 볼 수 있을 것이다. 참고로 int 로 형변환 하는 것은 File 객체의 length() Method의 반환값이 long 이기 때문에 형변환을 해준 것이다.

이제 여러개의 File을 Upload를 해보자. 또 이렇게 Upload 된 File을 Database의 Table에 저장해 보도록 하자. Table의 구조는 아래와 같다. MySQL 의 test Database에 만들도록 하자.

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>

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

이제 위의 HTML Form에서 넘어가는 File 들과 Parameter 들을 받아서 저장해줄 JSP File이 필요하다.

아래의 File이 그 역할을 해주는 File이다.

예) 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"; // Upload 경로
          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());
          */

          // 넘어오는 Parameter.
          String userName = multi.getParameter("userName");
          String subject = multi.getParameter("subject");
          String contents = multi.getParameter("contents");

          // 넘어오는 File Name
          String fileName1 = multi.getFilesystemName("up1");
          String fileName2 = multi.getFilesystemName("up2");
          String fileName3 = multi.getFilesystemName("up3");

          // File Size 받기
          int size1 = (int)(new File(savePath + "/" + fileName1).length());
          int size2 = (int)(new File(savePath + "/" + fileName2).length());
          int size3 = (int)(new File(savePath + "/" + fileName3).length());

          // Database 접속
          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");
          }
%>

위의 File보게 되면 넘어오는 Parameter를 request 객체로 받지 않고 request 를 MultipartRequest 에 매개변수로 넘겨준 후 MultipartRequest 의 Instance인 Multi 로 받아낸다는 것을 볼 수 있다.

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

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

File의 Size를 받는 부분은 File을 생성하고 그곳에 length() Method를 호출하여 int 로 형변환 하였다는 것을 볼 수 있다.

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

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

Database에 저장할 때는 File의 이름과 File의 Size를 입력해주면 된다.

위에서 받아온 File의 이름을 PreparedStatement 의 IN Parameter에 각각 대입을 해주고 executeUpdate 된 숫자를 받아주면 Database에 잘 입력이 되었는가의 판단 여부를 알아 낼 수 있다. 만약 Database에 입력이 잘 되었다면 1 이 반환될 것이고 그렇지 않다면 0 이 반납이 되기 때문이다. 이렇게 나온 숫자를 이용하여 Database에 입력이 안되었다면 기존의 Upload 된 File들을 지워줘야 한다.

MultipartRequest Class의 Method 중에는 File 입력 Parameter들의 이름을 Enumeration 객체로 반납해 주는 Method가 있다.

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

이렇게 알게 된 File의 실제 이름을 File 객체로 생성하여 delete() Method를 호출하게 되면 Upload 된 File이 Server 측에서 삭제되게 된다.

만약 Database에 잘 입력이 되었다면 upList.jsp File로 요청이 넘어가게 되는데 upList.jsp File에서는 Database에 입력되어 있는 모든 Record를 num 순서의 역방향(desc) 로 정렬하여 사용자 측에 보여주게 된다.

아래의 그림은 upList.jsp File 이다. 제목을 Click하면 Upload 된 게시물의 내용과 Upload 된 File을 볼 수가 있다.

그림 . upList.jsp



그럼 Database에는 어떻게 들어가 있는지 보자. MySQL Server가 깔려있는 경로로 이동하여 mysql –u root –p test 라고 입력한 후 Password를 입력한다.

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



아래는 upList.jsp File의 Source이다.

예제 : 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.*" %>

<%
          // Database 접속
          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 그림과 같이 잘 보인다면 제목을 Click 해 보자. upView.jsp 로 Page가 이동되는 것을 알 수 있다. 이제 upView.jsp 에서 해야 할 일이 머릿속에 그려질 것이다.

먼저 해야 할 일은 upList.jsp 에서 넘어오는 Parameter의 값을 받아내야 한다.

그 후 num 값을 이용하여 Query를 전송하고 또 그렇게 얻어지는 결과치를 Browser에 알맞게 뿌려주면 된다. 또한 File들에 대하여 Link를 걸어줘야 File을 Client 측에서 인식을 할 수가 있게 된다.

현재는 File에 대해 File 이름을 직접 지정하지만 추후 제작할 Upload 게시판에서는 Download를 해주는 File을 제작할 것이다.

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

예제 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"));
          // Database 접속
          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();
%>

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



화면 하단에 보면 수정/삭제 부분이 보인다. 여기서 수정이란 기존의 File을 삭제하고 새로운 File을 올리겠다는 것이고 삭제는 기존의 File과 Database에 들어있는 정보를 같이 삭제 하겠다는 것이다.

그럼 삭제를 먼저 해보자. 위의 그림에서 보이는 것과 같이 삭제 라는 곳에 Mouse를 올리고 Browser 하단에 나오는 Link 정보를 보도록 하자 delete.jsp?num=1 과 같이 정보가 넘어가는 것을 알 수 있다.

delete.jsp File에서는 넘어오는 Parameter를 이용하여 Database에 Query를 하고 얻어진 File 이름을 이용하여 File을 삭제하고 다시 Database의 Record를 삭제하면 된다. 이 후, 정보가 잘 삭제되었다면 다시 upList.jsp File로 Page를 이동시켜주면 된다.

아래의 예제를 작성한 후 실행 해 보고 Windows 탐색기에서 File이 잘 삭제 되었는지 보고, Database에서는 Record가 잘 삭제 되었는지 확인해 보자.

예제. 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”);
%>

위의 File에서는 ResultSet 에서 나오는 Table 정보를 이용하여(ResultSetMetaData) 선택된 컬럼의 개수를 알아내고, 그렇게 알아낸 컬럼의 숫자만큼 순환문을 돌면서 파일 객체를 생성하여 Upload 된 File을 삭제 하는 것을 볼 수 있다. 이후 두번째 Query 문에서는 해당 Record를 삭제하는 Query를 Database에 전송한 다는 것을 알 수 있다.

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

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

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

수정을 하려면 새로운 내용과 새로운 File을 입력을 받을 수 있는 HTML Form이 필요하다. 또 이곳에서 넘어가는 Parameter들에 대하여 작업을 해야 할 JSP File도 필요하다.

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

예제. 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 File은 생각보다 상당히 단순하다. 그냥 HTML 입력 Form에 Hidden 변수 Type만 추가된 형태이다.

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

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

예제. 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");
%>

위의 예제에서 보면 Query 문장을 순환문을 통해 작성을 한다는 것을 알 수가 있다. 이는 사용자가 새로 갱신될 File이나 내용을 어떻게 전송할 지 예측할 수가 없기 때문에 순환문을 통해 실제 Upload 된 Parameter에 해당하는 부분만 Query 문장에 포함을 시키려고 한 것이다.

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

JSP 배우러 가기~!!

저작자 표시 비영리 변경 금지
Creative Commons License

'Programming > JSP' 카테고리의 다른 글

JSP에서의 File Upload  (4) 2007/09/27
JSP, Servlet, Database 한글문제 총정리  (1) 2007/09/26
APM, Tomcat, JSP 설치 및 연동  (0) 2007/09/25
Posted by BLUEDAY™