본문 바로가기

JSP/PDS 02

PDS 02

작성자가 업로드한 파일명과 실제 저장된 파일명이 서로 다른 경우의 처리 예
파일 업로드부터 파일 다운로드 기능까지 모두 구현된 예제
개발환경: JDK1.6, Eclipse 3, Oracle 10g, SQL Developer, Apache Upload, Tomcat 6



자료실에  이미 중복된 이름의 파일이 존재한다면 새로 업로드되는 파일의 이름은 이용자가 지정한 파일명과 다른 이름으로 저장될 필요가 있다. 이런 경우에는 원래의 이름과 새로 변경한 이름을 모두 데이터베이스에 보관하고 있다가 원래의 이름으로 링크를 제시하고 실제 다운로드되는 파일은 이름이 변경된 파일을 전달해 주면 된다. 파일 다운로드 창에도 원래의 이름을 사용할 필요가 있다.

여기에 사용된 데이터베이스 테이블 구조나 앞서 작성된 내용은 여기를 참고하세요
Apache File Upload 라이브러리 설정은 여기를 참조

uploadForm.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><title>Upload page</title></head><body>
 <form action="ApacheUploadServlet" method="post" enctype="multipart/form-data" name="form1" id="form1">
   <center>
   <table border="2">
    <tr>
        <td align="center"><b>Multiple file Upload</td>
    </tr>
    <tr>
        <td><b>제 목: <input type="text" name="subject" value="PDS 테스트"></td>
    </tr>
       <tr>
        <td><b>올린이: <input type="text" name="name" value="김창운"></td>
    </tr>
       <tr>
        <td><b>설명: <input type="text" name="des" value="테스트용 업로드 파일"></td>
    </tr>
       <tr>
        <td>
         File 1: <input name="file" type="file">
     <td>
    </tr>
    <tr>
       <td>
       File 2:<input name="file" type="file">
    </td>
        <tr>
     <td>
        File 3:<input name="file" type="file">
     </td>
   </tr>
   <tr>
      <td align="center">
               <input type="submit" name="Submit" value="Submit files"/>
   </td>
   </tr>
    </table>
 <center>
 </form>
 </body>
 </html>


ApacheUploadServlet

package upload;

import java.io.*;
import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.disk.*;
import org.apache.commons.fileupload.servlet.*;
import org.apache.commons.io.*;

public class ApacheUploadServlet extends HttpServlet {
 private static final long serialVersionUID = 1L;

 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  request.setCharacterEncoding("euc-kr");
 boolean isMultipart = ServletFileUpload.isMultipartContent(request);
  if (!isMultipart) {
  }else {
     FileItemFactory factory = new DiskFileItemFactory();
     ServletFileUpload upload = new ServletFileUpload(factory);
     List items = null;
     try {
        items = upload.parseRequest(request);
     } catch (FileUploadException e) {
      e.printStackTrace();
     }
     Iterator itr = items.iterator();
     UploadInfo uploadInfo = new UploadInfo();
     while (itr.hasNext()) {
       FileItem item = (FileItem) itr.next();
       if (item.isFormField()) { // 파일이 아닌 폼필드에 입력한 내용을 가져옴.
         if(item!=null && item.getFieldName().equals("name")) {
           String name = item.getString("KSC5601");//form field 안에 입력한 데이터를 가져옴
           uploadInfo.setUserName(name);
           //System.out.println("전송자:"+name+"<br>");
         }else if(item!=null && item.getFieldName().equals("des")) {
           String des = item.getString("KSC5601");
           uploadInfo.setDes(des);
           //System.out.println("파일에 대한 설명:"+desc+"<br>");
         }else if(item!=null && item.getFieldName().equals("subject")) {
           String subject = item.getString("KSC5601");
           uploadInfo.setSubject(subject);
         }
      } else { // 폼 필드가 아니고 파일인 경우
     try {
        String itemName = item.getName();//로컬 시스템 상의 파일경로 및 파일 이름 포함
        if(itemName==null || itemName.equals("")) continue;
        String fileName = FilenameUtils.getName(itemName);// 경로없이 파일이름만 추출함
        // 파일이름 중복검사 및 그에 따른 새이름 설정
        File f = checkExist(fileName);
        item.write(f);// 지정 경로에 파일을 저장함
        uploadInfo.getFileMap().put(fileName, f.getName());// 원래이름, 변경된 이름을 맵에 저장
     } catch (Exception e) { e.printStackTrace(); }
    } // end of else
   }  // end of while
   PDS_DAO dao = new PDS_DAO();
   boolean ok = dao.savePDS(uploadInfo);
   request.setAttribute("result", ok);
   request.setAttribute("uploadInfo", uploadInfo);
   request.getRequestDispatcher("/uploadResult.jsp").forward(request, response);
  }   // end of else
 }  // end of doPost
 
 /* 이미 동일이름의 파일이 존재하면 새로 저장되는 파일의 이름 변경 */
 private File checkExist(String fileName){
       File f = new File("D:/upload/"+fileName);
       if(f.exists()) {
        StringBuffer sb = new StringBuffer(fileName);
        sb.insert(sb.lastIndexOf("."),"-"+new Date().getTime());
        f = new File("D:/upload/"+sb.toString());
       }
  return f;
 }

}



upploadResult.jsp

<%@page import="java.util.*"%>
<%@page import="java.io.File"%>
<%@page import="upload.UploadInfo"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<% UploadInfo info = (UploadInfo)request.getAttribute("uploadInfo");
 HashMap<String,String> fileMap = info.getFileMap();
 Set<String> keys = fileMap.keySet();
 Iterator<String> iterator = keys.iterator();
 
 boolean ok = (Boolean)request.getAttribute("result");
 String msg = ok ? "성공적으로 자료를 저장했습니다" : "저장중 오류발생, 저장실패";
%>
<!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>파일 업로드 정보</title>
<style>
 th{text-align: right; height:30px;}
 td{text-align: left; height:30px;}
 caption { font-size: 17pt; }
</style>
</head>
<body>
<center><br/><br/>
<%=msg%>
 <table border="1" cellspacing="0" cellpadding="5">
  <caption>파일 업로드 결과</caption>
  <tr><th>제 목</th><td><%=info.getSubject()%></td></tr>
  <tr><th>작성자</th><td><%=info.getUserName()%></td></tr>
  <tr><th>설 명</th><td><%=info.getDes()%></td></tr>
  <tr><th>파일명</th><td>
   <%
    while(iterator.hasNext()) {
     String originName = iterator.next();
     String changedName = fileMap.get(originName);%>
     <a href="DownloadServlet?file=<%=originName%>"><%=originName%></a> :
     <%=changedName%>
     <br/>
<%    }
   %>
  </td></tr>
 </table>

</center>
</body>
</html>




UploadInfo

package upload;

import java.io.*;
import java.util.*;

public class UploadInfo {
 
 private int num;
 private String subject;
 private String userName;
 private String des;
 private HashMap<String, String> fileMap = new HashMap<String, String>();
 private java.sql.Date wdate;
 
 public int getNum() {
  return num;
 }
 public java.sql.Date getWdate() {
  return wdate;
 }
 public void setNum(int num) {
  this.num = num;
 }
 public void setWdate(java.sql.Date wdate) {
  this.wdate = wdate;
 }
 public String getSubject() {
  return subject;
 }
 public void setSubject(String subject) {
  this.subject = subject;
 }
 public String getUserName() {
  return userName;
 }
 public String getDes() {
  return des;
 }
 public void setUserName(String userName) {
  this.userName = userName;
 }
 public void setDes(String des) {
  this.des = des;
 }
 public HashMap<String, String> getFileMap() {
  return fileMap;
 }
 public void setFileMap(HashMap<String, String> fileMap) {
  this.fileMap = fileMap;
 }

}


PDS_DAO

package upload;

import java.io.*;
import java.sql.*;
import java.util.*;

import javax.naming.*;
import javax.sql.*;

public class PDS_DAO {
 
 public Connection getConn() throws NamingException, SQLException{
  
   Context initCtx = new InitialContext();   
   Context envCtx = (Context) initCtx.lookup("java:comp/env");   
   DataSource ds = (DataSource) envCtx.lookup("jdbc/myoracle");   
   Connection conn = ds.getConnection();
   return conn;
 }
 
 /* PDS테이블과 UPLOAD_FILES테이블은 참조관계가 설정되어 있어야 함 */
 public boolean savePDS(UploadInfo info){
  String sql1 = "insert into pds values (PDS_NUM_SEQ.nextval, ?,?,?,sysdate)";
  String sql2 = "insert into upload_files values(FILE_NUM_SEQ.nextval, PDS_NUM_SEQ.currval,?,?)";
  Connection conn = null;
  PreparedStatement pstmt = null;
  try{
   conn = getConn();
   conn.setAutoCommit(false);
   /* 파일이 아닌 텍스트 정보는 PDS 테이블에 저장함 */
   pstmt = conn.prepareStatement(sql1);
   pstmt.setString(1, info.getSubject());
   pstmt.setString(2, info.getUserName());
   pstmt.setString(3, info.getDes());
   int n = pstmt.executeUpdate();
   
  /* 첨부파일명은 다른 테이블(upload_files)에 저장함 */
   pstmt = conn.prepareStatement(sql2);
   String[][] fileName = getFileNames(info.getFileMap());
   for(int i=0;i<fileName.length;i++){
    pstmt.setString(1, fileName[i][0]);
    pstmt.setString(2, fileName[i][1]);
    n += pstmt.executeUpdate();
   }
   conn.commit();
   if(n==1+fileName.length) return true;
   
  }catch(Exception e){
   try{
    conn.rollback();
   }catch(SQLException sqle){sqle.printStackTrace();}
   e.printStackTrace();
  }finally{
   closeAll(null, pstmt, conn);
  }
  return false;
 }
  
 /* 맵에 저장된 파일명을 추출하여 배열로 리턴한다 */
 private String[][] getFileNames(HashMap<String,String> fileMap){
  int len = fileMap.size();
  String[][] fileName = new String[len][2];
  
  Set<String> keys = fileMap.keySet();
  Iterator<String> it = keys.iterator();
  int idx = 0;
  while(it.hasNext()){
   String key = it.next();
   String val = fileMap.get(key);
   fileName[idx][0] = key;
   fileName[idx][1] = val;
   idx++;
  }
  return fileName;
 }
 

 public ArrayList<UploadInfo> getListByPage(int page) {
  String sql =
   "select * from ( " +
    "select t1.*, rownum rn from ( " +
     "select num, subject, author, des, wdate from pds order by wdate desc " +
    ") t1 " +
   ") where rn between ? and ?";
   
  int begin = page*5-(5-1);
  int end = page*5;
  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try{
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   pstmt.setInt(1, begin);
   pstmt.setInt(2, end);
   rs = pstmt.executeQuery();
   ArrayList<UploadInfo> list = new ArrayList<UploadInfo>();
   while(rs.next()){
    UploadInfo info = new UploadInfo();
    info.setNum(rs.getInt("NUM"));
    info.setSubject(rs.getString("SUBJECT"));
    info.setUserName(rs.getString("AUTHOR"));
    info.setWdate(rs.getDate("WDATE"));
    list.add(info);
   }
   return list;
  }catch (Exception e) {
   e.printStackTrace();
  }finally{
   closeAll(rs,pstmt,conn);
  }
  return null;
 }
 
 public int getRowCount(){
  String sql = "select count(*) from pds";
  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try {
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   
   rs = pstmt.executeQuery();
   if(rs.next()){
    int rowCount = rs.getInt(1);
    return rowCount;
   }
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   closeAll(rs, pstmt, conn);
  }
  return 0;
 }


 public UploadInfo getPdsByNum(int num) {
  String sql = "select p.num, p.subject, p.author, p.des, p.wdate, " +
  "f.file1, f.file2 from pds p, upload_files f " +
  "where p.num=? and p.num=f.pds_num";
  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try {
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   pstmt.setInt(1, num);
   rs = pstmt.executeQuery();
   UploadInfo info = new UploadInfo();
   while(rs.next()){
    /* 첨부파일명이 다수개인 경우에는 파일명만 다른 여러개의 레코드가 검색되므로 처음 한번만 저장하면 되고
        파일명은 각 레코드마다 받아 저장한다.   
    */
    if(info.getNum()==0){
      info.setNum(rs.getInt(1));
      info.setSubject(rs.getString(2));
      info.setUserName(rs.getString(3));
      info.setDes(rs.getString(4));
      info.setWdate(rs.getDate(5));
    }
    info.getFileMap().put(rs.getString(6), rs.getString(7));
   }
   return info;
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   closeAll(rs, pstmt, conn);
  }
  return null;
 }
 
 /* 이용자가 업로드할 때의 파일명을 이용하여 실제로 저장된 파일명을 찾아 리턴한다. */
 public String getRealName(int pds_num, String file1) {
  String sql = "select file2 from pds p, upload_files f " +
  "where p.num=? and f.file1=?";
  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try {
   conn = getConn();
   pstmt = conn.prepareStatement(sql);
   pstmt.setInt(1, pds_num);
   pstmt.setString(2, file1);
   rs = pstmt.executeQuery();
   if(rs.next()){
    return rs.getString("FILE2");
   }
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   closeAll(rs, pstmt, conn);
  }
  return null;
 }
 
 private void closeAll(ResultSet rs, PreparedStatement pstmt, Connection conn){
  try{
   if(rs!=null) rs.close();
   if(pstmt!=null) pstmt.close();
   if(conn!=null){
    conn.setAutoCommit(true);
    conn.close();
   }
  }catch(Exception e){
   e.printStackTrace();
  }
 }
}



PdsContServlet

package upload;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

public class PdsContServlet extends HttpServlet {
 private static final long serialVersionUID = 1L;

 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  request.setCharacterEncoding("euc-kr");
  String cmd = request.getParameter("cmd");
  if(cmd==null || cmd.equals("list")){
   String pg = request.getParameter("page");
   int page = 1;
   if(pg!=null && !pg.equals("")){
    page = Integer.parseInt(pg);
   }
   PDS_DAO dao = new PDS_DAO();
   request.setAttribute("list", dao.getListByPage(page));
   forward("/pdsList.jsp?pg="+page, request, response);
  }else if(cmd.equals("read")){
   int num = Integer.parseInt(request.getParameter("num"));
   PDS_DAO dao = new PDS_DAO();
   UploadInfo info = dao.getPdsByNum(num);
   request.setAttribute("info", info);
   forward("/pdsRead.jsp",request, response);
  }
 }
 
 private void forward(String target, HttpServletRequest req, HttpServletResponse res){
  try {
   req.getRequestDispatcher(target).forward(req, res);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

}



pdsList.jsp
<%@page import="upload.*"%>
<%@page import="java.util.*"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<jsp:useBean id="pageUtil" class="util.paging.PageUtilBean" scope="page">
 <jsp:setProperty name="pageUtil" property="currPage" param="pg" />
 <jsp:setProperty name="pageUtil" property="numsPerPage" value="5"/>
 <jsp:setProperty name="pageUtil" property="link" value="PdsContServlet?cmd=list" />
</jsp:useBean>
<%
 ArrayList<UploadInfo> list = (ArrayList<UploadInfo>)request.getAttribute("list");
%>
<!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>PDS List</title>
<style>
  a:link { text-decoration: none; }
 a:visited { text-decoration: none; }
 a:hover{ color:red; }
 a:active { text-decoration: none; }
 caption { font-size: 17pt;
    font-family: fantasy;
   font-style: bold;
  }
</style>
</head>
<body>
<center><br/><br/>
<table border="1" cellspacing="0" width="500" height="200">
 <caption> PDS List</caption>
 <tr><th>번호</th><th>제 목</th><th>작성자</th><th>날 짜</th></tr>
 <%
  for(int i=0;i<list.size();i++){
   UploadInfo info = list.get(i); %>
   <tr><td><%=info.getNum()%></td>
   <td>
    <a href="PdsContServlet?cmd=read&num=<%=info.getNum()%>"><%=info.getSubject()%></a>
   </td>
   <td><%=info.getUserName()%></td>
   <td><%=info.getWdate()%></td></tr>
  <%}
 %>
</table>
<jsp:getProperty name="pageUtil" property="navStr"/>
</center>
</body>
</html>



pdsRead.jsp
<%@page import="java.util.*"%>
<%@page import="upload.*"%>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%
 UploadInfo info = (UploadInfo) request.getAttribute("info");
 HashMap<String,String> fileMap = info.getFileMap();
 Set<String> keys = fileMap.keySet();
 Iterator<String> it = keys.iterator();
%>
<!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>PDS 읽기</title>
<style>
 th{ text-align: right; }
 td{ text-align: left; }
</style>
<script>
 function download(pds_num, file1){
  form1.pds_num.value = pds_num;
  form1.file.value = file1;
  form1.submit();
 }
</script>
</head>
<body>
<form name="form1" action="DownloadServlet" method="post">
 <input type="hidden" name="cmd" value="download"/>
 <input type="hidden" name="pds_num"/>
 <input type="hidden" name="file"/>
</form>
<br/><br/><center>
<table border="1" cellspacing="0" width="500" height="270" cellpadding="5">
 <tr><th>번 호</th><td><%=info.getNum()%></td></tr>
 <tr><th>작성자</th><td><%=info.getUserName()%></td></tr>
 <tr><th>제 목</th><td><%=info.getSubject()%></td></tr>
 <tr><th>설 명</th><td><%=info.getDes()%></td></tr>
 <tr><th>날 짜</th><td><%=info.getWdate()%></td></tr>
 <tr><th>첨 부</th>
 <td>
  <%
   int num = info.getNum();
   while(it.hasNext()){
    String file1 = it.next(); %>
    <a href="javascript:download(<%=num%>,'<%=file1%>');"><%=file1%></a><br/>
  <% }
  %>
 </td></tr>
</table>
</center>
</body>
</html>



DownloadServlet.java

package upload;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

 public class DownloadServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

 protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   response.setContentType("application/octet-stream;charset=KSC5601");
   String fileName = request.getParameter("file"); // 8859_1 형식만 헤더에 설정할 수 있음
   //아래처럼 attachment 를 사용하면 브라우저는 무조건 다운로드 창을 띄우고 파일명을 보여준다.
   response.setHeader("Content-Disposition", "attachment;filename="+fileName+";");

   ServletOutputStream sos = null;
   try{
    sos = response.getOutputStream();
   }catch(Exception e){e.printStackTrace();}
  
   // 원래파일명을 이용하여 실제 저장된 파일명을 가져온다.
   int pds_num = Integer.parseInt(request.getParameter("pds_num"));
   fileName = new String(fileName.getBytes("8859_1"),"KSC5601"); //파일에 접근하기 위해 한글로 인코딩
   PDS_DAO dao = new PDS_DAO();
   String realName = dao.getRealName(pds_num, fileName);
  
   //다음과 같이 스트림을 열고 브라우저에 바이트 데이터를 전송해주면 된다.
   FileInputStream fio = null;
   File inFile = new File("D:/upload/"+realName);
   byte[] buf = null;
   if(inFile.exists()) {
    int len = (int)inFile.length();
    buf = new byte[len];
   }
   fio = new FileInputStream("D:/upload/"+realName);
   fio.read(buf);
   sos.write(buf);
   sos.flush();
   fio.close();
   sos.close();
 }
}


PageUtilBean.java

package util.paging;

import upload.*;

public class PageUtilBean {
 private int rows; // DB에 저장된 총 레코드 수
 private int currPage; // 이용자가 요청한 페이지 번호
 private int rowsPerPage = 5; // 한 화면에 출력할 DB레코드 수
 // 위의 값은 DAO 클래스에서 한페이지에 가져오는 레코드수와 일치해야 함
 private int numsPerPage = 3; // 한 화면의 하단에 출력할 페이지번호 수
 private int totalPages;
 private String link = "BoardServlet?cmd=list"; // 페이지번호를 클릭하면 이동할 링크
 private String paramName = "page"; // 페이지번호 파라미터 이름 (예, BoardServlet?cmd=list&page=3)
 private String leftSign = "《"; // 페이지번호가 많아서 한 화면을 넘을 때 이전으로 이동하는 링크
 private String rightSign = "》"; // 다음 링크
 private String leftEnd = "["; // 처음 페이지로 이동
 private String rightEnd = "]";// 마지막 페이지로 이동
 /* 위의 속성들은 페이지 번호에 링크를 적용한 문자열을 작성할 때 사용됨
  * 예: <a href="BoardServlet?cmd=list&page=5">5</a>
  * 브라우저 출력 결과 [《5 7 8 9 10》]
  */
 
 public PageUtilBean() {
  // 해당 DAO로부터 테이블에 저장된 전체 레코드 수를 얻는다
  rows = new PDS_DAO().getRowCount();
 }
 
 /* JSP에서 이 메소드를 호출하여 페이지 이동 링크를 출력하면 된다*/
 public String getNavStr() {
  // 총 레코드 수 구함
  // 총 페이지 수 구함
  // 현재 페이지가 포함될 페이지 수열 결정
  // 현재 페이지에 하단에 보여줄 링크 열 작성
  // 왼쪽 이동 기호 출력여부 결정
  // 오른쪽 이동 기호 출력여부 결정
  totalPages = getTotalPages();
  int n = currPage/numsPerPage;
  n += currPage%numsPerPage==0 ? 0 : 1;
  int begin = n*numsPerPage-(numsPerPage-1);
  int end = n*numsPerPage;
  if(end>totalPages) end = totalPages;
  
  StringBuffer sb = new StringBuffer();
  String pgNum = null;

  for(int i=begin;i<=end;i++){
   if(i==currPage) pgNum = "<span style=\"color:red;font-size:17pt;\">"+i+"</span>";
   else pgNum = String.valueOf(i);
   
   sb.append("<a href=\""+link+"&"+paramName+"="+i+"\">"+pgNum+"</a>&nbsp;&nbsp;");
  }
  if(begin!=1)sb.insert(0, "<a href=\""+link+"&"+paramName+"="+(begin-1)+"\"> "+leftSign+"&nbsp;&nbsp;</a> ");
  if(end<totalPages)sb.append(" <a href=\""+link+"&"+paramName+"="+(end+1)+"\">&nbsp;&nbsp;"+rightSign+" </a>");
  sb.insert(0, "<a href=\""+link+"&"+paramName+"=1\">"+leftEnd+"&nbsp;&nbsp;</a> ");
  sb.append("<a href=\""+link+"&"+paramName+"="+totalPages+"\">&nbsp;&nbsp;"+rightEnd+"</a>");

  return sb.toString();
 }

 public int getRows() {
  return rows;
 }

 public void setRows(int rows) {
  this.rows = rows;
 }

 /* JSP에서 현재 페이지 번호를 사용하려면 호출 */
 public int getCurrPage() {
  return currPage;
 }
 public int getRowsPerPage() {
  return rowsPerPage;
 }
 public int getNumsPerPage() {
  return numsPerPage;
 }
 
 /* JSP에서 총 레코드 수를 사용하려면 호출 */
 public int getTotalPages() {
  totalPages = rows/rowsPerPage;
  totalPages += rows%rowsPerPage==0 ? 0 : 1;
  return totalPages;
 }
 public String getLink() {
  return link;
 }
 public String getParamName() {
  return paramName;
 }
 public String getLeftSign() {
  return leftSign;
 }
 public String getRightSign() {
  return rightSign;
 }
 public void setCurrPage(int currPage) {
  this.currPage = currPage;
 }
 public void setRowsPerPage(int rowsPerPage) {
  this.rowsPerPage = rowsPerPage;
 }
 public void setNumsPerPage(int numsPerPage) {
  this.numsPerPage = numsPerPage;
 }
 public void setTotalPages(int totalPages) {
  this.totalPages = totalPages;
 }
 public void setLink(String link) {
  this.link = link;
 }
 public void setParamName(String paramName) {
  this.paramName = paramName;
 }
 public void setLeftSign(String leftSign) {
  this.leftSign = leftSign;
 }
 public void setRightSign(String rightSign) {
  this.rightSign = rightSign;
 }
 //public void setNavStr(String navStr) {
 // this.navStr = navStr;
 //}
}