티스토리 뷰

게시판에 파일 업로드, 다운로드 기능을 넣어보자. 


자바는 파일을 올리고 받는 것을 원래 지원해주지 않는다. 그래서 두군데서 이를 지원한다.

1. 오레일리에서 배포하고 있는 servlets.com (2008년 업데이트가 마지막)

2. 아파치에서 배포하고 있는  Commons 자료 (2014년 업데이트가 마지막)


그래서. 아파치에서 배포하는 FileUpload를 사용해보려고 한다. 홈페이지에 접속하여 FileUpload 클릭! IO도 함께 받는다! 

가장 최신 버전 zip파일로 다운로드!



- fileUpload : commons-fileupload-1.3.1.jar를 복사하여 WEB-INF 밑에 lib 에 붙여넣기 한다.

- iO : commons-io-2.4.jar를 복사하여 WEB-INF 밑에 lib 에 붙여넣기 한다.


참고 : 이게 jsp에서 파일을 첨부하는 기본 형식이라고 한다

<form method="POST" enctype="multipart/form-data" action="fup.cgi">
  File to upload:
<input type="file" name="upfile"><br/>
  Notes about the file:
<input type="text" name="note"><br/>
 
<br/>
 
<input type="submit" value="Press"> to upload the file!
</form>


// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();

// Configure a repository (to ensure a secure temp location is used)
ServletContext servletContext = this.getServletConfig().getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory
.setRepository(repository);

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);

// Parse the request
List<FileItem> items = upload.parseRequest(request);



FileVO.java

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 
package com.ktds.smahn.file.vo;
 
public class FileVO {
 
    private int fileId;
    private int articleId;
    private String fileName;
    private String fileLocation;
 
    public int getFileId() {
        return fileId;
    }
 
    public void setFileId(int fileId) {
        this.fileId = fileId;
    }
 
    public int getArticleId() {
        return articleId;
    }
 
    public void setArticleId(int articleId) {
        this.articleId = articleId;
    }
 
    public String getFileName() {
        return fileName;
    }
 
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
 
    public String getFileLocation() {
        return fileLocation;
    }
 
    public void setFileLocation(String fileLocation) {
        this.fileLocation = fileLocation;
    }
 
}
 
cs


FileBiz.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
package com.ktds.smahn.file.biz;
 
import com.ktds.smahn.file.dao.FileDAO;
import com.ktds.smahn.file.vo.FileVO;
 
public class FileBiz {
    
    private FileDAO fileDAO;
 
    public FileBiz() {
        fileDAO = new FileDAO();
    }
    
    public void insertFile(FileVO file) {
        fileDAO.insertOneFile(file);
    }
 
}
 
cs



FileDAO.java

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
 
package com.ktds.smahn.file.dao;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
 
import com.ktds.smahn.file.vo.FileVO;
import com.ktds.smahn.member.dao.Const;
import com.ktds.smahn.util.xml.XML;
 
public class FileDAO {
 
    public void insertOneFile(FileVO file) {
        
        int insertCount = 0;
        
        
        loadOracleDriver();
 
        Connection conn = null;
        PreparedStatement stmt = null;
 
        try {
 
            conn = DriverManager.getConnection(Const.DB_URL, Const.DB_ID, Const.DB_PASSWORD);
 
            String query = XML.getNodeString("//query/file/insertOneFile/text()");
            stmt = conn.prepareStatement(query);
 
            stmt.setInt(1, file.getArticleId());
            stmt.setString(2, file.getFileName());
            stmt.setString(3, file.getFileLocation());
 
            insertCount = stmt.executeUpdate();
 
            if (insertCount > 0) {
                stmt.close();
                System.out.println("파일 테이블 입력 성공");
            }
 
        } catch (SQLException e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeDB(conn, stmt, null);
        }                
            
    }
    
    public List<FileVO> getFileListbyArticleId(int articleId){
        
        loadOracleDriver();
 
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
 
        try {
 
            conn = DriverManager.getConnection(Const.DB_URL, Const.DB_ID, Const.DB_PASSWORD);
 
            String query = XML.getNodeString("//query/file/getFileListbyArticleId/text()");
            stmt = conn.prepareStatement(query);
 
            stmt.setInt(1, articleId);
            rs = stmt.executeQuery();
            
            List<FileVO> fileList = new ArrayList<FileVO>();
            
            FileVO file = null;
            
            while ( rs.next() ) {
                file = new FileVO();
                file.setFileId(rs.getInt("FILE_ID"));
                file.setFileName(rs.getString("FILE_NAME"));
                file.setFileLocation(rs.getString("FILE_LOCATION"));
                fileList.add(file);
            }
            
            if( file == null ){
                //jstl에서 not empty 를 해서 체크하기 편함
                return null;
            }
            
            return fileList;
 
        } catch (SQLException e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeDB(conn, stmt, rs);
        }            
    }
    
    private void loadOracleDriver() {
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
 
    private void closeDB(Connection conn, PreparedStatement stmt, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
            }
        }
 
    }
 
}
 
cs



이렇게 만들고나서 이제 우리는 아래 클래스를 이용해서 파일업로드를 해줄꺼다. 

이 클래스를 util 폴더 밑에 복붙해준다.

MultipartHttpServletRequest.java

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package com.ktds.smahn.util;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
 
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
 
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
 
public class MultipartHttpServletRequest {
 
    private HttpServletRequest request;
    private List<FileItem> items;
    
    public MultipartHttpServletRequest(HttpServletRequest request) {
        this.request = request;
        
        // Create a factory for disk-based file items
        DiskFileItemFactory factory = new DiskFileItemFactory();
 
        // Configure a repository (to ensure a secure temp location is used)
        ServletContext servletContext = request.getServletContext();
        File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
        factory.setRepository(repository);
 
        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setHeaderEncoding("UTF-8"); 
        
        try {
            items = upload.parseRequest(request);
        } catch (FileUploadException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
    
    public String getParameter(String name) {
        for ( FileItem fileItem : items ) {
            if ( fileItem.getFieldName().equals(name) )  {
                try {
                    return fileItem.getString("UTF-8");
                } catch (UnsupportedEncodingException e) {
                    return fileItem.getString();
                }
            }
        }
        return null;
    }
    
    public List<String> getParameterValue(String name) {
        List<String> values = new ArrayList<String>();
        
        for ( FileItem fileItem : items ) {
            if ( fileItem.getFieldName().equals(name) )  {
                try {
                    values.add(fileItem.getString("UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    values.add(fileItem.getString());
                }
            }
        }
        return values;
    }
    
    public HttpSession getSession() {
        return request.getSession();
    }
    
    public RequestDispatcher getRequestDispatcher(String jspPage) {
        return request.getRequestDispatcher(jspPage);
    }
    
    public MultipartFile getFile(String name) {
        MultipartFile file = new MultipartFile();
        
        for ( FileItem fileItem : items ) {
            if ( fileItem.getFieldName().equals(name) )  {
                file.setFileName(fileItem.getName());
                file.setFileSize(fileItem.getSize());
                file.setContentType(fileItem.getContentType());
                file.setFileItem(fileItem);
                
                return file;
            }
        }
        
        return null;
    }
    
    public class MultipartFile {
        private String fileName;
        private long fileSize;
        private String contentType;
        private FileItem fileItem;
        
        public String getFileName() {
            return fileName;
        }
        public void setFileName(String fileName) {
            this.fileName = fileName;
        }
 
        public long getFileSize() {
            return fileSize;
        }
        public void setFileSize(long fileSize) {
            this.fileSize = fileSize;
        }
 
        public String getContentType() {
            return contentType;
        }
        public void setContentType(String contentType) {
            this.contentType = contentType;
        }
        
        public void setFileItem(FileItem fileItem) {
            this.fileItem = fileItem;
        }
        
        public File write(String dest) {
            File file = new File(dest);
            try {
                fileItem.write(file);
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            return file;
        }
        
    }
    
}
 
 
 
cs


그리고 이 클래스는 다운로드할때 필요한 클래스! 역시 util 폴더 안에 복사 붙여넣기 해준다.

DownloadUtil.java

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
 
package com.ktds.smahn.util;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class DownloadUtil {
 
    private String uploadPath;
    
    public String getUploadPath() {
        return uploadPath;
    }
    public void setUploadPath(String uploadPath) {
        this.uploadPath = uploadPath;
    }
    
    private static DownloadUtil downloadUtil;
    
    private DownloadUtil() {}
    
    public static DownloadUtil getInstance(String filePath) {
        
        if ( downloadUtil == null ) {
            downloadUtil = new DownloadUtil();
        }
        
        downloadUtil.setUploadPath(filePath);
        
        return downloadUtil;
    }
    
    public void download(HttpServletRequest request,
                        HttpServletResponse response,
                        String realFileName,
                        String displayFileName) throws UnsupportedEncodingException {
        
        File downloadFile = new File(this.getUploadPath() + File.separator + realFileName);
        
        response.setContentType("application/download; charset=utf-8");
        response.setContentLength( (int) downloadFile.length());
        
        // 사용자의 브라우져 정보를 가져온다.
        String userAgent = request.getHeader("User-Agent");
        // 사용자의 브라우저가 MicroSoft Internet Explorer 인지 확인한다.
        boolean internetExplorer = userAgent.indexOf("MSIE"> -1;
        if!internetExplorer ) {
            internetExplorer = userAgent.indexOf("Gecko"> -1;
        }
        
        // 다운로드할 파일의 이름을 브라우져별로 가져온다.
        String fileName = new String(displayFileName.getBytes(), "UTF-8");
        if ( internetExplorer ) {
            fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+""%20");
        }
        else {
            // File의 이름을 UTF-8 타입에서 ISO-8859-1 타입으로 변경한다.
            fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
        }
        
        // 브라우져가 받을 파일의 이름을 response에 등록한다.
        response.setHeader("Content-Disposition",
                "attachment; filename=\"" + fileName + "\";");
        // 브라우져가 다운로드 받은 후 Binary 파일로 생성하라고 보낸다.
        response.setHeader("Content-Transfer-Encoding""binary");
        
        FileInputStream fin = null;
        FileChannel inputChannel = null;
        WritableByteChannel outputChannel = null;
        
        try {
            fin = new FileInputStream(downloadFile);
            inputChannel = fin.getChannel();
 
            outputChannel = Channels.newChannel(response.getOutputStream());
            inputChannel.transferTo(0, fin.available(), outputChannel);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            try {
                if (outputChannel.isOpen())
                    outputChannel.close();
            } catch (Exception e) {}
            try {
                if (inputChannel.isOpen())
                    inputChannel.close();
            } catch (Exception e) {}
            try {
                if (fin != null)
                    fin.close();
            } catch (Exception e) {}
        }
    }
    
}
 
cs



그리고 file 만을 위한 서블릿은 당연히 따로 필요가 없다. 글쓰는 폼에 칼럼을 추가해주기만 하면 되고 버튼을 눌렀을 때 파일 정보도 함께 넘겨받으면 되니깐!!!!

write.jsp

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<jsp:include page="/WEB-INF/view/common/header.jsp"></jsp:include>
<script type="text/javascript">
    $(document).ready(function () {
        
        <c:if test="${empty article}">
            $("#doWrite").click(function () {
                
                var form = $("#writeForm");
                form.attr("method""post");
                form.attr("action""<c:url value="/doWrite"/>");
                form.submit();
            });
        </c:if>
        
        <c:if test="${not empty article}">
            $("#doModify").click(function () {
                var form = $("#writeForm");
                form.attr("method""post");
                form.attr("action""<c:url value="/doModify"/>");
                form.submit();
            });
            $("#reset").click(function () {
                /* $("#title").val("${article.title}");
                $("#description").val("${article.description}"); */
                
                //현재 페이지 새로고침
                location.reload();
            });
        </c:if>
 
        $("#cancel").click(function () {
            location.href="<c:url value="/list"/>";
        });
        
        
    });
</script>
 
 
<form id="writeForm" enctype="multipart/form-data">
    
    <table>
        <tr>
            <td>Title</td>
            <td>
                <input     type="text" 
                        id="title" name="title" style="width: 250px; height: 40px;" 
                        value="${ article.title }" />    
            </td>
        </tr>
        <tr>
            <td>Description</td>
            <td>
                <textarea id="description" name="description" style="width: 250px; height: 150px;">${article.description}</textarea>
            </td>
        </tr>
        <tr>
            <td> 파일 첨부
            </td>
            <td>
                <input type="file" id="file" name="file" />
            </td>
        </tr>
    </table>
    <!-- article이 비어있다면 글쓰기 화면  -->
    <c:if test="${ empty article }">
        <input type="button" id="doWrite" value="등록!" />
        <input type="reset" value="다시 쓰기" />
    </c:if>
    
    <!-- article이 비어있지 않다면 수정 화면 -->
    <c:if test ="${ not empty article }">
        <input type="hidden" name="articleId" value="${article.articleId}" />
        <input type="button" id="doModify" value="수정!" />
        <input type="button" id="reset" value="다시 쓰기" />
    </c:if>
    
    <input type="button" id="cancel" value="취소" />
 
 
</form>
 
<jsp:include page="/WEB-INF/view/common/footer.jsp"></jsp:include>
cs



DoWriteServlet.java

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package com.ktds.smahn.article.web;
 
import java.io.File;
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import com.ktds.smahn.article.biz.ArticleBiz;
import com.ktds.smahn.article.vo.ArticleVO;
import com.ktds.smahn.file.biz.FileBiz;
import com.ktds.smahn.file.vo.FileVO;
import com.ktds.smahn.member.vo.MemberVO;
import com.ktds.smahn.util.MultipartHttpServletRequest;
import com.ktds.smahn.util.Root;
import com.ktds.smahn.util.MultipartHttpServletRequest.MultipartFile;
 
/**
 * Servlet implementation class DoWriteServlet
 */
public class DoWriteServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private ArticleBiz articleBiz;
    private FileBiz fileBiz;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public DoWriteServlet() {
        super();
        articleBiz = new ArticleBiz();
        fileBiz = new FileBiz();
        
    }
 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
 
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        
        MultipartHttpServletRequest multipartRequest = new MultipartHttpServletRequest(request);
        
        String title = multipartRequest.getParameter("title");
        String description = multipartRequest.getParameter("description");
        MultipartFile mpfile = multipartRequest.getFile("file");
        File upFile = mpfile.write("D:\\"+ mpfile.getFileName());
 
        HttpSession session = request.getSession();
        MemberVO loginMember = (MemberVO) session.getAttribute("_MEMBER_");
        
        ArticleVO article = new ArticleVO();
        article.setTitle(title);
        article.setDescription(description);
        article.setMemberId(loginMember.getMemberId());
            
        articleBiz.insertArticle(article);
        
        int articleId = articleBiz.getArticleId();
        
        if ( articleId > 0 ){
            
            if( mpfile.getFileSize() != 0 ){
                
                FileVO file  = new FileVO();
                file.setArticleId(articleId);
                file.setFileName(mpfile.getFileName());
                file.setFileLocation("D:\\"+ mpfile.getFileName());
                
                fileBiz.insertFile(file);
                
            }
            response.sendRedirect(Root.get(this+ "/list");
            return;
        }
        else{
            System.out.println("등록 실패");
        }
 
    }
 
}
 
cs



결과화면!!

1) 글쓰기 화면


2) 등록 버튼 누른 뒤의 화면


3) 게시글 상세보기 화면

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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 27 28 29 30 31
글 보관함