기존 게시판에 파일 관련 기능을 넣어서 자료실 형태로 만들어 보자.

자료실을 만들기 위해서는 기존 기능에 다음과 같이 파일 관련 기능을 넣어주면 된다.

  • 사용자가 글을 쓰면서 파일을 첨부하기 때문에, 글쓰기에 파일 태그(input type=file)를 추가해 주어야 한다.
  • 글 저장 컨트롤에서는 전송된 파일을 받아서 지정된 디렉터리에 저장하고 그 파일 이름을 게시물과 같이 데이터 베이스에 저장한다.
  • 글 수정은 글 쓰기와 같지만 첨부한 파일을 삭제할 수 있는 방법이 있어야 한다.
  • 게시판 리스트에서는 첨부 파일이 있는 경우 이미지 등의 방법으로 파일이 있다는 것을 보여 준다.
  • 글 읽기에서는 첨부된 파일 리스트를 보여주고 파일명을 클릭하면 다운로드 받을 수 있게 한다.
  • 글 삭제는 게시 글이 삭제 될 때 첨부 파일도 같이 삭제한다.

파일을 서버에 저장할 때 고려해야 할 사항이 몇 가지 있다.

먼저, 첨부한 파일을 서버에 어떻게 저장할 것인가 하는 문제이다. 

사용자가 첨부한 파일은 “xxx.jpg” 등과 같은 이름을 가지게 되는데

간혹 서버에서 실행 가능한 “xxx.jsp”, “xxx.js” 등으로 지정하여 많은 문제(해킹 등)를 발생시킬 수 있다.

따라서 저장할 때는 별도의 이름으로 저장해야 된다.

사용자가 명명한 파일명과 서버에 저장될 때의 파일명이 필요하다는 의미이다.

두 번째는 지정된 게시물과 첨부한 파일명이 같이 저장해야 된다는 것이다. 

당연한 것이지만 그렇게 해야 다운로드, 삭제 등이 가능하기 때문이다.

같이 저장하는 방식은 게시물이 저장된 테이블(TBL_BOARD)에 필드를 추가해서 처리할 것인지,

별도의 테이블에 처리할 것인지를 고려해야 한다.

첨부파일이 하나일 경우 같은 테이블에 저장하기도 하지만 대부분 하나 이상의 파일을 첨부하기 때문에 별도 테이블로 처리하는 것이 좋다.

이상의 두 가지를 고려해서 다음과 같이 첨부 파일을 저장하는 테이블(TBL_BOARDFILE)을 생성해야 한다.

CREATE TABLE TBL_BOARDFILE (
    FILENO INT(11)  NOT NULL AUTO_INCREMENT,   -- 파일 번호
    BRDNO INT(11),                                                -- 글번호
    FILENAME VARCHAR(100),                                -- 파일명
    REALNAME VARCHAR(30),                                -- 실제파일명
    FILESIZE INT,                                                   -- 파일 크기
    PRIMARY KEY (FILENO)
);

파일 번호(FILENO)는 첨부파일에 대한 기본 키 값으로 저장된 순서를 의미한다.

BRDNO는 게시판(TBL_BOARD)의 글 번호를 의미하는 것으로 게시물과 파일의 관련성을 나타낸다.

즉, 해당 게시물(BRDNO)의 모든 파일 파일을 가지고 오는데 사용한다.

FILENAME은 사용자가 첨부할 때의 원래 파일 이름을 의미하고, 

REALNAME은 서버에 저장하면서 새롭게 부여된 실제 파일명을 의미한다.

실제 파일명(REALNAME)은 날짜와 시간(millisecond)을 이용하여 중복되지 않게 부여하는데 30 자 이내로 저장한다.



'Java > 게시판 4:자료실' 카테고리의 다른 글

2. 자료실 - 글쓰기  (0) 2016.03.28
3. 자료실 - 글 수정  (3) 2016.03.28
4. 자료실 - 리스트  (0) 2016.03.28
5. 자료실 - 글 읽기 / 삭제  (0) 2016.03.26

파일을 첨부하기 위해서는 글 쓰기 폼(boardForm.jsp)에 file 태그만 추가해 주면 된다.

다음 코드에서 빨갛게 표시된 것처럼 uploadfile파일이라고 이름을 주고 생성하였다. 

Multiple 속성은 한 번에 여러 개의 파일을 지정할 수 있다.

<input type="file" name="uploadfile" multiple="" />

이러한 첨부 파일을 전송하기 위해 폼 태그도 인코딩 타입(enctype)을 multipart/form-data로 지정해 줘야 한다. 

이것은 파일이나 용량이 큰 데이터를 전송할 때 지정하는 방식으로 기억해두면 될 것 같다.

<form name="form1" action="board4Save" method="post" enctype="multipart/form-data">
    <table border="1" style="width:600px">
        ~~ 생략 ~~
            <tr>
                <td>내용</td>

                <td><textarea name="brdmemo" rows="5" cols="60"><c:out value="${boardInfo.brdmemo}"/></textarea></td>
            </tr>
            <tr>
                <td>첨부</td>
                <td>
                    <input type="file" name="uploadfile" multiple="" />

boardForm.jsp

사용자가 파일을 첨부하여 전송한 내용을 서버에서 받기 위해 스프링에서 제공하는 MultipartFile를 다음 코드와 같이 boardVO에 추가해 줘야 한다.

다수의 파일을 전송하기 때문에 List 형태로 지정해야 하고 변수 이름(uploadfile)은 파일 태그에서 지정한 이름과 같아야 한다.

public class boardVO {

    private String brdno, brdtitle, brdwriter, brdmemo, brddate, brdhit, brddeleteflag;
    private List<MultipartFile> uploadfile;

    ~~ 생략 ~~
    public List<MultipartFile> getUploadfile() {
        return uploadfile;
    }


    public void setUploadfile(List<MultipartFile> uploadfile) {
        this.uploadfile = uploadfile;
    }

boardVO.java

파일을 저장하기 위해서 관련 내용을 boardVO로 받아온 뒤에 처리를 하게 된다.

먼저, MultipartFile로 받아온 파일들을 서버의 지정된 디렉터리에 저장해야 한다.

본 예제에서는 FileUtil라는 클래스로 이 기능을 미리 개발해 두었다. 

복잡하지 않기 때문에 원리를 이해하면 좋겠지만 여기에서는 saveAllFiles만 호출하면 된다는 것을 기억해 두자. 

다만 FileUtil 안에 저장 디렉터리로 "d:\\workspace\\fileupload\\"가 지정되어 있으니 각자의 디렉터리 구조에 맞추어 수정해줘야 하다.

@RequestMapping(value = "/board4Save")
public String boardSave(HttpServletRequest request, boardVO boardInfo) throws Exception {
    FileUtil fs = new FileUtil();

    List<FileVO> filelist = fs.saveAllFiles(boardInfo.getUploadfile());

    boardSvc.insertBoard(boardInfo, filelist);

    return "redirect:/board4List";
}

board4Ctr.java

주의: 파일명은 날짜와 시간(millisecond)을 이용하여 중복되지 않게 부여하고, 각 파일은 해당 년도 디렉터리에 저장하게 된다.

디렉터리는 파일명의 앞 4자리(년도)를 잘라서 자동 생성되고 그 디렉터리에 파일이 저장된다.

하나의 디렉터리에 저장될 수 있는 파일의 개수는 한정적(약 만개로 기억)이라 년도 별로 저장하게 개발하였다.

만약, 1년간 파일의 개수가 제한된 개수를 넘는다면 년월(앞6자리)로 수정해 주면 된다.


첨부된 파일이 실제 디렉터리에 저장되면 FileVO 형의 List가 반환된다.

FileVO는 파일 첨부 기능이 있는 모든 페이지에서 비슷하게 사용하기 때문에 공통(common)으로 제작하였다.

클래스 구성은 테이블(TBL_BOARDFILE) 구조와 유사하지만

테이블의 글번호(brdno) 대신에 부모글 번호(parentPK)로 명명하여 공통으로 사용할 수 있게 구성하였다.

size2String 함수는 비트로 저장된 파일 크기(filesize)를 byte, K-byte, M-Byte 등으로

적절하게 변환하여 반환하는 함수로 공통 함수로 구성하여 사용해도 되지만

FileVO 외에서는 사용할 일이 없어서 FileVO에 넣어서 제작하였다.

사용된 공식은 몇 년 전 인터넷에서 찾은 것으로 간단해서 익혀두면 조금이나마 알고리즘 연습이 될 수 있을 것이다.

package gu.common;

public class FileVO {
    private Integer fileno;         // 글번호
    private String parentPK;     // 부모 글번호
    private String filename;     // 파일명
    private String realname;    // 실제파일명
    private long filesize;        // 파일 크기
   
    public String size2String() {
        Integer unit = 1024;
        if (filesize < unit){
            return String.format("(%d B)", filesize);
        }
        int exp = (int) (Math.log(filesize) / Math.log(unit));

        return String.format("(%.0f %s)", filesize / Math.pow(unit, exp), "KMGTPE".charAt(exp-1));
    }

   
    public Integer getFileno() {
        return fileno;
    }

    public void setFileno(Integer fileno) {
        this.fileno = fileno;
    }
    ~~ 생략 ~~

FileVO.java

원리는 로그(log)를 이용한 것으로 밑수가 10인 로그(상용로그)를 실행하면 10의 배수가 계산된다.

byte, K-byte, M-Byte 등은 1024배씩 커지는 것으로 약 10의 3배수씩 커진다고 보면 된다.

즉, 1 K byte = 1024 byte 이고 1024 byte 는 Log를 취하면 약 3(3.010)의 값이 나온다.

이 3은 10의 자릿수로 보면 된다 (1000으로 보면 0의 개수).

예로, 파일 크기(filesize)가 2248 byte일 경우 로그를 취하면 약 3(3.351)이 나오고

단위 (1024의 로그값 3)로 나누면 1(1.11)이 계산 된다.

즉, 단위를 나타내는 문자열("KMGTPE")에서 첫 번째 K가 선택되게 된다.

단위를 구했으면 단위에 맞게끔 파일 크기를 계산해 줘야 한다.

단위값(1024)을 거듭제곱(power)으로 1을 계산하면 1024가 나오고 이 값을 실제 파일 크기 2248에 대하여 나누면 2.19가 계산된다.

따라서 최종적으로 2.2 K byte로 표기되는 것이다.

이렇게 반환된 파일 리스트(filelist)는 게시물 내용과 같이 서비스(insertBoard)로 전달하여 데이터 베이스에 저장한다.

public void insertBoard(boardVO param, List<FileVO> filelist) throws Exception {
        if (param.getBrdno()==null || "".equals(param.getBrdno()))
               sqlSession.insert("insertBoard4", param);
        else sqlSession.update("updateBoard4", param);

        for (FileVO f : filelist) {
            f.setParentPK(param.getBrdno());
           sqlSession.insert("insertBoard4File", f);
        }
}

board4Svc.java

서비스에서는 파일 리스트 개수만큼 반복해서 다음과 같이 Insert문으로 첨부

테이블(TBL_BOARDFILE)에 저장하면 된다.

게시물의 글번호(brdno)를 parentPK에 넣고(setParentPK), mybatis에서는 INSERT문을 #{parentPK}로 만들어 실행하게 된다. 

<insert id="insertBoard4File" parameterType="gu.common.FileVO" >
        INSERT INTO TBL_BOARDFILE (BRDNO, FILENAME, REALNAME, FILESIZE)
        VALUES (#{parentPK}, #{filename}, #{realname}, #{filesize})
</insert>

board4.xml

게시판 테이블(TBL_BOARD)에 저장하는 insertBoard4의 SQL문도 수정이 필요하다.
위 SQL의 insertBoard4File에 게시판의 글번호(brdno) 값이 필요하다.
글 수정일 경우 글번호가 같이 넘어 오지만
신규 글 쓰기일 경우 글번호가 부여 되지 않았다.
특히, 글 쓰기는 글번호가 Insert문이 실행되면 DBMS가 자동으로 부여하기 때문에 그 번호를 알 수 없다.
따라서, 자동으로 부여하지 않고 계산해서 가져와야 한다.
자동으로 부여 하는 방법은 현재 테이블에 저장된 번호 중 최대값(MAX)을 구하고, 그 값에 1을 더하면 된다.


            SELECT IFNULL(MAX(BRDNO),0)+1 FROM TBL_BOARD


IFNULL은 null일 때 0값을 주는 것으로 MAX 함수가 null 일 경우는 데이터가 하나도 없는 경우를 의미한다.
즉, 첫 데이터를 입력하기 전이다.
이렇게 반환 된 값으로 게시판 글번호로 저장하고 첨부 파일에도 저장하면 된다.
따라서 insertBoard4 서비스에 위 SELECT문을 실행할 수 있도록 하면 되지만,
Mybatis의 selectKey를 이용하면 쉽게 해결 할 수 있다.
다음 코드와 같이 selectKey의 keyProperty에 글번호(brdno)를 지정하면 신규 글번호 값이 boardVO 클래스의 brdno에 넣어져 반환 된다.
이 값이 INSERT문에서 #{brdno}로 사용해주면 새로운 게시물이 잘 저장된다.
그리고, 파라메타로 넘어온 boardVO 클래스에 저장되어 반환되기 때문에,
f.setParentPK(param.getBrdno())로 글번호를 받아와서 사용할 수 있게 된다.

<insert id="insertBoard4" parameterType="gu.board4.boardVO" >
        <selectKey resultType="String" keyProperty="brdno" order="BEFORE">
            SELECT IFNULL(MAX(BRDNO),0)+1 FROM TBL_BOARD
       </selectKey>
  
       INSERT INTO TBL_BOARD(BRDNO, BRDTITLE, BRDWRITER, BRDMEMO, BRDDATE, BRDHIT, BRDDELETEFLAG)
                              VALUES (#{brdno}, #{brdtitle}, #{brdwriter}, #{brdmemo}, NOW(), 0, 'N' )
</insert>

board4.xml

마지막으로 다음과 같이 트랜잭션(Transaction) 처리를 해주어야 한다.

앞서 insertBoard 서비스(board4Svc)에서 기존에 게시물 저장 후에

첨부한 파일 리스트들을 저장하는 SQL문을 실행하도록 추가했다.

즉 2개의 트랜잭션이 발생하는 경우에,

앞의 게시물을 저장하고 여러 가지 원인으로 오류가 발생 할 경우 첨부 파일 정보는 저장되지 않는다.

데이터 무결성에 문제가 발생한다.

이러한 경우 모든 데이터가 저장 안되게 처리하게 되는데 

다음과 같이 try 문을 사용하여 오류가 생기면 앞서 작업한 내용을 모두 취소(rollback)하고

오류가 없으면 모두 저장(commit)하도록 작성한다.

txManager 클래스는 이미 applicationContext.xml에 선언되어 있는 것으로 그냥 트랜잭션에 사용되는 것으로 기억하고 넘어간다.

DefaultTransactionDefinition ~~클래스 등은 트랜잭션 사용시 나오는 상용 구문 정도로 기억하면 될 듯하다.

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);

try{
    if (param.getBrdno()==null || "".equals(param.getBrdno()))
           sqlSession.insert("insertBoard4", param);
    else sqlSession.update("updateBoard4", param);

    for (FileVO f : filelist) {
        f.setParentPK(param.getBrdno());
        sqlSession.insert("insertBoard4File", f);
    }
    txManager.commit(status);
} catch (Exception ex) {

    txManager.rollback(status);
    throw ex;
}     

board4Svc.java

본 예제는 첨부한 파일을 "d:\workspace\fileupload\"에 저장한다.

지정된 디렉터리에 대한 운영체제의 권한에 따라 권한오류(특히 리눅스)가 발생하면서 파일이 저장 되지 않으니 주의해야 한다.




'Java > 게시판 4:자료실' 카테고리의 다른 글

1. 자료실 - 준비 & 시작  (1) 2016.04.02
3. 자료실 - 글 수정  (3) 2016.03.28
4. 자료실 - 리스트  (0) 2016.03.28
5. 자료실 - 글 읽기 / 삭제  (0) 2016.03.26

자료실에서 글 수정의 핵심은 다음 그림과 같이 기존에 첨부한 파일을 삭제할 수 있게 하는 것이다.



새로 첨부하는 것은 글쓰기와 수정이 하나로 처리되어 있기 때문에 별도의 처리가 필요치 않다.

먼저, 게시물과 같이 첨부 파일 리스트를 가져오도록 구성해 줘야 한다.

@RequestMapping(value = "/board4Form")
public String boardForm(HttpServletRequest request, ModelMap modelMap) throws Exception {
    String brdno = request.getParameter("brdno");
    if (brdno!=null) {
        boardVO boardInfo = boardSvc.selectBoardOne(brdno);
        List<?> listview = boardSvc.selectBoard4FileList(brdno);
   
        modelMap.addAttribute("boardInfo", boardInfo);
        modelMap.addAttribute("listview", listview);
    }
   
    return "board4/boardForm";
}

board4Ctr.java

다음 SELECT문은 첨부 테이블(TBL_BOARDFILE)에서 게시글에 해당하는 데이터를 가져오는 것으로,

서비스에 selectBoard4FileList를 추가해 주고,

컨트롤에서는 이 서비스를 호출하여 넘겨받은 List를 게시물 정보(boardInfo)와 같이 modelMap에 넣어(listview) jsp로 넘겨준다.

<select id="selectBoard4FileList" resultType="gu.common.FileVO" parameterType="String">
        SELECT FILENO, FILENAME, REALNAME, FILESIZE
          FROM TBL_BOARDFILE
         WHERE BRDNO=#{brdno}
         ORDER BY FILENO DESC
    </select>

baord4.xml

글 수정(쓰기) 폼에서는 listview의 개수만큼 반복(foreach)하여 파일 명을 보여주고 사용자가 선택하면 삭제 할 수 있도록 한다.

즉, 파일명을 보여 줄 때 사용자가 삭제하고자 선택 할 수 있는 checkbox를 주고

이름은 fileno로 동일하게 부여 하고 값(value)은 각 첨부 파일의 파일 번호(fileno)를 주도록 한다.

<form name="form1" action="board4Save" method="post" enctype="multipart/form-data">
    <table border="1" style="width:600px">
        ~~ 생략 ~~
            <tr>
                <td>내용</td>
                <td><textarea name="brdmemo" rows="5" cols="60"><c:out value="${boardInfo.brdmemo}"/></textarea></td>
            </tr>
            <tr>
                <td>첨부</td>
                <td>
                    <c:forEach var="listview" items="${listview}" varStatus="status">
                        <input type="checkbox" name="fileno" value="<c:out value="${listview.fileno}"/>">   
                        <a href="fileDownload?filename=<c:out value="${listview.filename}"/>&downname=<c:out value="${listview.realname}"/>">
                        <c:out value="${listview.filename}"/></a> <c:out value="${listview.size2String()}"/><br/>
                    </c:forEach>                   
               
                    <input type="file" name="uploadfile" multiple="" />

boardForm.jsp

예로 파일 이름과 번호(fileno)가 1, 2, 3인 경우 각각의 체크 박스가 동일한 이름으로 선택할 수 있게 생성하는 것이다. 

사용자가 1, 3 번을 선택하면 서버로 이 값이 배열로 fileno에 저장되어 전송된다.


파일명을 선택하면 해당 파일이 다운로드(fileDownload) 되도록 제작하였다.

fileDownload 컨트롤은 해당 파일명을 파라메타로 넘겨주면 지정된 파일을 찾아서 클라이언트로 전송해 준다.

fileDownload도 공통으로 사용하는 것으로 원리는 넘어가니 사용법만 기억해 두자.

파라메터 filename은 사용자가 입력한 파일명(filename)이고, downname은 서버에서 저장한 실제 파일명(realname)을 지정해 준다.

fileDownload에도 파일 경로가 고정되어 있으니 자신에게 맞게끔 수정하면 된다.


사용자가 삭제하기 위해 선택한 파일번호들을

다음과 같이 getParameterValues를 이용하여 배열로 받아와서 처리한다.

@RequestMapping(value = "/board4Save")
public String boardSave(HttpServletRequest request, boardVO boardInfo) throws Exception {
    String[] fileno = request.getParameterValues("fileno");

    FileUtil fs = new FileUtil();
    List<FileVO> filelist = fs.saveAllFiles(boardInfo.getUploadfile());

    boardSvc.insertBoard(boardInfo, filelist, fileno);

    return "redirect:/board4List";
}

board4Ctr.java


컨드롤에서 받은 파일번호들을(fileno) Delete문을 이용하여 삭제하면 개발이 끝나게 된다.

배열 변수 하나을 Mybatis로 넘길 수 없기 때문에,

배열변수를 가지는 클래스를 생성하거나 HashMap 클래스를 이용해야 한다.

본 예제에서는 후자를 이용했다.

public void insertBoard(boardVO param, List<FileVO> filelist, String[] fileno) throws Exception {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = txManager.getTransaction(def);
        
        try{
            if (param.getBrdno()==null || "".equals(param.getBrdno()))
                 sqlSession.insert("insertBoard4", param);
            else sqlSession.update("updateBoard4", param);
   
            if (fileno != null) {
                HashMap p = new HashMap();
                p.put("fileno", fileno) ;
                sqlSession.insert("deleteBoard4File", p);
            }

            for (FileVO f : filelist) {
                f.setParentPK(param.getBrdno());
                    sqlSession.insert("insertBoard4File", f);
            }
            txManager.commit(status);
        } catch (Exception ex) {
            txManager.rollback(status);
            throw ex;
        }            
}

board4Svc.java

Mybatis에서 넘겨 받은 삭제할 파일 번호들을 foreach문을 사용하여 삭제 하게 된다.

넘겨 받은 파일번호(fileno)의 배열 값을 콤마(,)로 생성하고

SQL문의 저장되어 있기 때문에 IN을 사용하여 한번에 지정된 모든 파일 정보를 삭제한다.

<delete id="deleteBoard4File" parameterType="hashmap">
    DELETE
      FROM TBL_BOARDFILE
         WHERE FILENO IN (
              <foreach item="item" index="index" collection="fileno" separator=",">
                     ${item}
              </foreach> 
        )    
</delete>

baord4.xml

삭제할 파일이 1번과 3번 파일이면 deleteBoard4File은 다음과 같은 SQL 문을 실행하게 될 것이다.

DELETE FROM TBL_BOARDFILE WHERE FILENO IN (1, 3)

클래스나 HashMap에 넘겨서 처리하는 방법외에

하나의 DELETE 문을 배열의 개수 만큼 반복 실행하는 방법도 있지만

개인적으로 데이터 입출력 횟수가 적은 것을 선호해서 이러한 방법을 사용했다.


앞서서 게시물 삭제를 실제로 삭제하지 않고 플래그(deleteflag) 처리하였는데 첨부 파일도 그렇게 구현할 수 있다. 

더욱이 실제 파일을 삭제하는 코드는 구현하지 않았는데 컨트롤에서 java delete 함수를 이용해 파일 삭제도 해보길 …

'Java > 게시판 4:자료실' 카테고리의 다른 글

1. 자료실 - 준비 & 시작  (1) 2016.04.02
2. 자료실 - 글쓰기  (0) 2016.03.28
4. 자료실 - 리스트  (0) 2016.03.28
5. 자료실 - 글 읽기 / 삭제  (0) 2016.03.26

리스트에서는 첨부 파일이 있는지 여부를 적절한 아이콘으로 보여준다.

리스트에서 다운로드 받게끔 하는 경우도 있지만 본 예제에서는 첨부 개수를 보여주어 첨부 파일 존재 여부만 표시 했다.


먼저, SQL에서 다음과 같이 subquery를 이용하여 첨부 파일 개수를 세어준다.

해당 게시물의 글번호(TB.BRDNO)에 맞는 첨부 파일의 게시물 번호(BRDNO)를 맞는 개수를 세는 것이다.

<select id="selectBoard4List" resultType="gu.board4.boardVO" parameterType="gu.common.SearchVO">
        SELECT BRDNO, BRDTITLE, BRDWRITER, DATE_FORMAT(BRDDATE,'%Y-%m-%d') BRDDATE, BRDHIT
                  , (SELECT COUNT(*) FROM TBL_BOARDFILE WHERE BRDNO=TB.BRDNO) FILECNT
          FROM TBL_BOARD TB
         <include refid="includeBoard"/>
         ORDER BY BRDNO DESC
         LIMIT ${rowStart-1}, 10
    </select>

baord4.xml

subquery의 필드명을 filecnt로 지정하고 boardVO에 추가해 준다.

public class boardVO {

    private String brdno, brdtitle, brdwriter, brdmemo, brddate, brdhit, brddeleteflag
                     , filecnt;
    ~~ 생략 ~~
    public String getFilecnt() {
        return filecnt;
    }

    public void setFilecnt(String filecnt) {
        this.filecnt = filecnt;
    }

boardVO.java

마지막으로 jsp 파일에서 첨부 파일 개수(filecnt)를 보여주는 열을 다음과 추가하고 실행하여 결과를 확인하면 된다.

        <thead>
            <tr>
                <th>번호</th>
                <th>제목</th>
                <th>등록자</th>
                <th>등록일</th>
                <th>조회수</th>
                <th>첨부</th>
            </tr>
        </thead>
        <tbody>
            <c:forEach var="listview" items="${listview}" varStatus="status">   
                <c:url var="link" value="board4Read">
                    <c:param name="brdno" value="${listview.brdno}" />
                </c:url>       
                <tr>
                    <td><c:out value="${searchVO.totRow-((searchVO.page-1)*searchVO.displayRowCount + status.index)}"/></td>
                    <td><a href="${link}"><c:out value="${listview.getShortTitle(35)}"/></a></td>
                    <td><c:out value="${listview.brdwriter}"/></td>
                    <td><c:out value="${listview.brddate}"/></td>
                    <td><c:out value="${listview.brdhit}"/></td>
                    <td><c:out value="${listview.filecnt}"/></td>
                </tr>
            </c:forEach>
        </tbody>

boardList.jsp



'Java > 게시판 4:자료실' 카테고리의 다른 글

1. 자료실 - 준비 & 시작  (1) 2016.04.02
2. 자료실 - 글쓰기  (0) 2016.03.28
3. 자료실 - 글 수정  (3) 2016.03.28
5. 자료실 - 글 읽기 / 삭제  (0) 2016.03.26

글 읽기에서는 파일을 다운로드 받을 수 있도록 해주면 된다.


파일을 다운로드 받을 수 있게 해주는 것은 글 수정에서 처리 되었다.

글 수정에서 사용된 서비스와 방법을 그대로 사용하면 된다.

@RequestMapping(value = "/board4Read")
       public String board4Read(HttpServletRequest request, ModelMap modelMap) throws Exception {
       
        String brdno = request.getParameter("brdno");
       
        boardSvc.updateBoard4Read(brdno);
        boardVO boardInfo = boardSvc.selectBoardOne(brdno);
        List<?> listview = boardSvc.selectBoard4FileList(brdno);
       
        modelMap.addAttribute("boardInfo", boardInfo);
        modelMap.addAttribute("listview", listview);
       
        return "board4/boardRead";
    }

board4Ctr.java

다운로드 받도록 하는 링크를 생성하는 방법은 글 수정과 동일하지만 파일 삭제를 위해 제공한 체크 박스가 없다는 차이가 있다.

<tr>
    <td>첨부</td>
    <td>
        <c:forEach var="listview" items="${listview}" varStatus="status">   
            <a href="fileDownload?filename=<c:out value="${listview.filename}"/>&downname=<c:out value="${listview.realname }"/>">
            <c:out value="${listview.filename}"/></a> <c:out value="${listview.size2String()}"/><br/>
        </c:forEach>                   
    </td>
</tr>

boardRead.jsp

글 삭제에 따른 파일 처리는 별도로 하지 않았다.

글 삭제로 게시물이 삭제되면 별도의 처리를 하지 않아도 관계된 파일들이 화면에 나오지 않기 때문에 다른 처리를 하지 않았다. 

실제 파일도 삭제 하지 않았는데, 필요한 경우 컨트롤(boardDelete)에 파일 삭제 처리를 넣어주면 된다.








'Java > 게시판 4:자료실' 카테고리의 다른 글

1. 자료실 - 준비 & 시작  (1) 2016.04.02
2. 자료실 - 글쓰기  (0) 2016.03.28
3. 자료실 - 글 수정  (3) 2016.03.28
4. 자료실 - 리스트  (0) 2016.03.28

+ Recent posts