struts 1 - File Uplod & File Download

Published on: 2009. 7. 1. 16:06 by louis.dev

1. File Upload

-업로드는 FormFile class로 처리한다.
-DB테이블은 FormFile class 자체가 들어갈 수 없음으로 파일의 정보를 담을 것들(크기,이름..)을 COLUMN으로 생성한다. 여기서는 파일의 이름과 크기를 COLUMN으로 설정한다.

File Upload에는 3가지 해야 할 것이 있다.
① 저장할 디렉터리 위치를 어디로 할 것 인가?
② 용량 제한은 얼마로 할 것 인가?
③ 중복파일에 대해서 해결책은 어떻게 할 것인가?
        - 1/1000초 로 계산하여 파일 이름 변경
        - 파일 명 뒤에 숫자 붙여서 저장 - 많이 사용한다.

작성방법

1) apache.org -> commons -> IO 와 FileUpload library를 다운 받고 추가한다.

2) 데이터를 담을 DTO를 생성한다.
----------------------------------------------------------------------------------------------------
package com.myhome.upload.dto;

public class UploadDTO{
 
 /*entity property*/
 private int    num;
 private String name;
 private String sex;
 private String tel;
 private String wdate;
 private String fileName;
 private long   fileSize;

 
 
 public int getNum() {
  return num;
 }
 public void setNum(int num) {
  this.num = num;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getSex() {
  return sex;
 }
 public void setSex(String sex) {
  this.sex = sex;
 }
 public String getTel() {
  return tel;
 }
 public void setTel(String tel) {
  this.tel = tel;
 }
 public String getWdate() {
  return wdate;
 }
 public void setWdate(String wdate) {
  this.wdate = wdate;
 }
 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;
 }
 
 
}

----------------------------------------------------------------------------------------------------
DB에는 FormFile 자체가 들어가지 못하기 때문에 파일의 이름과 크기를 저장할 property를 설정한다.

3) ActionForm을 상속받은 bean class를 생성하고 각각의 property들을 설정한다.

UploadFormBean Class

----------------------------------------------------------------------------------------------------
package com.myhome.upload.beans;

import org.apache.struts.action.ActionForm;
import org.apache.struts.upload.FormFile;

@SuppressWarnings("serial")
public class UploadFormBean extends ActionForm implements java.io.Serializable{
 /*form property*/
 private int    num;
 private String name;
 private String sex;
 private String tel;
 private String wdate;
 
 /*upload property*/
 private FormFile file;

 public int getNum() {
  return num;
 }

 public void setNum(int num) {
  this.num = num;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getSex() {
  return sex;
 }

 public void setSex(String sex) {
  this.sex = sex;
 }

 public String getTel() {
  return tel;
 }

 public void setTel(String tel) {
  this.tel = tel;
 }

 public String getWdate() {
  return wdate;
 }

 public void setWdate(String wdate) {
  this.wdate = wdate;
 }

 public FormFile getFile() {
  return file;
 }

 public void setFile(FormFile file) {
  this.file = file;
 }
 
}

----------------------------------------------------------------------------------------------------
위에서 가장 중요한 부분은 FormFile로 file 을 선언하고 getter 와 setter를 생성한다는 점이다. jsp에서 넘어온 파일이 저 FormFile class에 담기게 된다.

4)저장하기 위해 SqlMap.xml을 생성한다.

5)DAO를 설정해 DB에 접근하게 한다.


----------------------------------------------------------------------------------------------------
package com.myhome.upload.dao;

import java.sql.SQLException;
import java.util.List;

 

import com.myhome.manager.SQLManager;
import com.myhome.upload.dto.UploadDTO;

public class UploadDAO extends SQLManager{
 
 public void insert(UploadDTO dto) throws SQLException{
  this.getSqlMap().insert("uploadInsert",dto);
 }
 @SuppressWarnings("unchecked")
 public List<UploadDTO> list() throws SQLException{
  return (List<UploadDTO>)this.getSqlMap().queryForList("uploadList");
 }
}
----------------------------------------------------------------------------------------------------

6) web.xml 에 struts-uploadModul.xml 의 init-param을 설정한다.
----------------------------------------------------------------------------------------------------
<init-param>
   <param-name>config/uploadModule</param-name>
   <param-value>/WEB-INF/config/struts-uploadModule.xml</param-value>
  </init-param>
----------------------------------------------------------------------------------------------------

7.) struts-uploadModul.xml에서 ActionForm을 사용하기 때문에 Form-bean설정과 <action></action>설정을 해준다.
----------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="euc-kr" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://struts.apache.org/dtds/struts-config_1_3.dtd">

<struts-config>

   <!-- Form Bean Definitions -->
   <form-beans>
      <form-bean name="uploadBean" type="com.myhome.upload.beans.UploadFormBean"/>
   </form-beans>


   <!-- Global Exception Definitions -->
 <global-exceptions>
  <exception type="java.lang.Exception"
       key="exception.global"
       path="/exception/exception.jsp"/>
 </global-exceptions>

   <!-- Global Forward Definitions -->
    <global-forwards>
    </global-forwards>


   <!-- Action Mapping Definitions -->
    <action-mappings>
       <action path="/toModule"
               type="org.apache.struts.actions.SwitchAction"/>
      
       <action path="/index"
          type="org.apache.struts.actions.ForwardAction"
          parameter="/register.jsp"/>
       
       <action path="/upload"
            name="uploadBean"
          scope="request"
          parameter="method"
          unknown="true"
          type="com.myhome.upload.actions.UploadDispatchAction">
         
       <!-- exception handle -->
       <exception key = "exception.handler"
            handler = "com.myhome.handler.InfoExceptionHandler"
            path = "/excetpion.jsp"
            type = "java.lang.NullPointerException">
       </exception>
           <forward name="result"  path="/result.jsp"/>
           <forward name="fail"    path="/fail.jsp"/>
           <forward name="list"    path="/list.jsp"/>
           <forward name="query"   path="/modify.jsp"/>
           <forward name="update"  path="/template.jsp"/>
           <forward name="delete"  path="/template.jsp"/>
       </action>   
      
       <action path="/download"
            type="com.myhome.upload.actions.FileDownloadAction">
       </action>
    
      
          
    </action-mappings>

   <!-- Controller Processor Definition -->
   <controller processorClass="com.myhome.info.processor.InfoRequestProcessor"/>

   <!-- Message Resources Definitions -->
 <message-resources parameter="com.myhome.upload.ExceptionMessageResource"/>
   <!-- Plug Ins Configuration -->
      <!-- Tiles plugin -->
      <!-- Validator plugin -->
    
</struts-config>


----------------------------------------------------------------------------------------------------


8) 업로드할때 쉽게 사용하기 위해 업로드 파일의 최대값과 저장 폴더를 설정한 UploadUtil class를 생성한다
----------------------------------------------------------------------------------------------------
package com.myhome.upload.util;

public final class UploadUtil {

 public static final String SAVE = "D://JAVA/Java Web2/edu/upload/";
 
 public static final String SIZE = "1024*1024*20";
}
----------------------------------------------------------------------------------------------------
- SAVE : 업로드된 파일을 저장하는 위치를 지정한다. 각 폴더 구조는 역슬레쉬(\)가 아닌 슬래쉬(/)로 표현한다
- SIZE : 업로드 파일의 최대를 설정한 것으로 20MB를 지정하고 있다.

9) 비지니스 로직을 구현하기 위해 각각의 Action 클래스를 상속받은 Action Class를 구현한다.
----------------------------------------------------------------------------------------------------
package com.myhome.upload.actions;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
import org.apache.struts.upload.FormFile;

import com.myhome.upload.beans.UploadFormBean;
import com.myhome.upload.dao.UploadDAO;
import com.myhome.upload.dto.UploadDTO;
import com.myhome.upload.util.UploadUtil;

public class UploadDispatchAction extends DispatchAction{
 
 public ActionForward register(ActionMapping mapping,
          ActionForm form,
          HttpServletRequest request,
          HttpServletResponse response)
          throws Exception{
  
  UploadFormBean bean = (UploadFormBean)form;
  UploadDTO dto = new UploadDTO();
  BeanUtils.copyProperties(dto, bean);
  if(bean.getFile() != null){
   this.upload(bean.getFile());
   dto.setFileName(bean.getFile().getFileName());
   dto.setFileSize(bean.getFile().getFileSize());
  }else{
   dto.setFileName("");
   dto.setFileSize(0L);
   new NullPointerException("파일을 올려주세요!!");
  }
  dto.setWdate(this.getWdate());
  
  new UploadDAO().insert(dto);
  request.setAttribute("dto", dto);
  return mapping.findForward("result");
 }
 public void upload(FormFile ff) throws Exception {
     InputStream is = ff.getInputStream();
     OutputStream os = new FileOutputStream(UploadUtil.SAVE + ff.getFileName());
     byte buffer[] = new byte[8192];
     int n = 0;
     while((n = is.read(buffer,0,8192)) != -1){
          os.write(buffer, 0, n);
     }
    
     is.close();
     os.close();
 }
 
 /*리스트 부분*/
 public ActionForward list(ActionMapping mapping,
         ActionForm form,
         HttpServletRequest request,
         HttpServletResponse response)
         throws Exception{
  
  request.setAttribute("list", new UploadDAO().list());
  
  return mapping.findForward("list");
 }
 
 protected String getWdate(){
  return new java.text.SimpleDateFormat("yyyy-MM-dd").format(new java.util.Date());
 }

}
----------------------------------------------------------------------------------------------------
가장중요한 부분은 보라색으로 색칠 해놓은 곳이다.(register method는 현재 등록만 한다고 생각한다.)
upload method의 버퍼 크기는 2의 n승으로 커지고 보통 2의 10승부터 사이즈를 적는다.
10) jsp 페이지에서 form 테그는 enctype=“multipart/form-data” 다음과 같이 변경한다.


<form method="post"   name="regform" action="toModule.do?prefix=/uploadModule&page=/upload.do" enctype="multipart/form-data">
          <input type="file" name="file">
</form>




2. File Download

다운로드시에는 struts 1 library에 포함되어있는 DownloadAction class를 상속 받아 getStreamInfo()를 override하여 File Download를 구현한다.

작업순서
1) struts-uploadModule.xml 에 <action></action>에 다운로드에 대한 Action을 선언한다.

<action path="/download"
            type="com.myhome.upload.actions.FileDownloadAction">
</action>

2) DownloadAction class를 상속받은 class를 만든다.
----------------------------------------------------------------------------------------------
package com.myhome.upload.actions;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;

/*download*/
import org.apache.struts.actions.DownloadAction;
import java.io.File;
import com.myhome.upload.util.UploadUtil;


public class FileDownloadAction extends DownloadAction {
 
 @Override
 protected StreamInfo getStreamInfo(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception {
  
        String filename = request.getParameter("clip");
       
        File file = new File(UploadUtil.SAVE + filename);
       
        /*한글파일일 경우 헤더타입이 다르므로 변경한다.*/
        String contentType = "application/octet-stream";
        response.setContentType(contentType);

       
        
        /*txt, image파일들은 브라우저가 직접 결과를 전달한다.  
         * 다음과 같이 설정하지 않을 경우 text파일 같은 경우는 브라우져에서
         * 해석이 가능함으로 브라우져에서 바로 열린다. 이것을 처리해 주면
         * 무조건 다운로드 된다.
         * */

       
        response.setHeader("Content-disposition",
                     "attachment;filename="+
                     toEng(file.getName()));
        response.setHeader("Content-Length", ""+file.length());
     
        return new FileStreamInfo(contentType, file);
   }
 
   public String toKor(String data){
     if(data == null)return null;
     String temp = "";
     try{
     temp = new String(data.getBytes("ISO8859_1"),"EUC-KR");
     }catch(java.io.UnsupportedEncodingException uee){}
     return temp;
   }
 
   public String toEng(String data){
     if(data == null)return null;
     String temp = "";
     try{
     temp = new String(data.getBytes("MS949"),"ISO-8859-1");
     }catch(java.io.UnsupportedEncodingException uee){}
     return temp;
   }

}
----------------------------------------------------------------------------------------------