'Servlet'에 해당되는 글 34건

  1. 2008.09.08 Log4j 사용법 로깅-Log4J
  2. 2008.09.08 MultipartRequest 로 파일 업로드 하기
  3. 2008.09.08 JSP: 파일 업로드 (cos.jar 이용) MultipartRequest를 통한 FIle Upload, Download, Delete
  4. 2008.09.08 Servlet API 파일
  5. 2008.09.08 session사용
  6. 2008.09.08 세션설정,세션에서 값 가져오기
  7. 2008.09.08 session.setAttribute 에서 주의할 점
  8. 2008.09.08 request 객체
  9. 2008.09.08 request.getAttribute
  10. 2008.09.08 jsp/Servlet 기본2
2008. 9. 8. 15:07

Log4j 사용법 로깅-Log4J

Log4j 사용법 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

Log4j 상세 설명 및 예제 프로그램

 

 

 

 

 

 

 

작성자:          <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />홍혜성 hicomet@nate.com

작성일:          200613

 

Log4j 사용 예제 프로그램(1)

[1] Log4jTest.java

 

import org.apache.log4j.Logger;

              

public class Log4jTest

{

        protected static final Logger logger = Logger.getLogger(Log4jTest.class);

              

        public static void main(String[] args)

        {

               if (logger.isDebugEnabled()) {

                       logger.debug("프로그램 DEBUG");

               }

               if (logger.isInfoEnabled()) {

                       logger.info("프로그램 INFO");

               }

                logger.warn("프로그램 WARN");

               logger.error("프로그램 ERROR");

               logger.fatal("프로그램 FATAL");

        }

}      

 

[2] log4j.properties

 

## info 이상만 출력 허용 (debug Priority은 출력되지 않음)

## ROOT appender R 로 지정함

log4j.rootCategory=info, R

              

## 콘솔에 출력

log4j.appender.R=org.apache.log4j.ConsoleAppender

              

## 패턴 : 날짜출력 Priority출력 클래스명출력 - 메시지출력 개행

log4j.appender.R.layout=org.apache.log4j.PatternLayout

log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c{2} %x - %m%n

 

[3] 결과

 

D:\study\log4j>javac Log4jTest.java

D:\study\log4j>java Log4jTest

2006-01-02 16:19:18,671 INFO  Log4jTest  - 프로그램 INFO

2006-01-02 16:19:18,671 WARN  Log4jTest  - 프로그램 WARN

2006-01-02 16:19:18,671 ERROR Log4jTest  - 프로그램 ERROR

2006-01-02 16:19:18,671 FATAL Log4jTest  - 프로그램 FATAL

 

Log4j 사용 예제 프로그램 (2)

 [1] Log4jTest.java

 

import org.apache.log4j.Logger;

import org.apache.log4j.PropertyConfigurator;

              

public class Log4jTest

{

        public static void main(String[] args)

        {

               // ROOT

               Logger rootLogger = Logger.getRootLogger();

               rootLogger.info("프로그램 시작");

              

               // Logger1

               Logger logger1 = Logger.getLogger("com.search1");

               if (logger1.isDebugEnabled()) {

                       logger1.debug("프로그램 DEBUG");

               }

               if (logger1.isInfoEnabled()) {

                       logger1.info("프로그램 INFO");

               }

               logger1.warn("프로그램 WARN");

               logger1.error("프로그램 ERROR");

               logger1.fatal("프로그램 FATAL");

                             

               // Logger2

               Logger Logger2 = Logger.getLogger("com.search2");

               if (Logger2.isDebugEnabled()) {

                       Logger2.debug("프로그램 DEBUG");

               }

               if (Logger2.isInfoEnabled()) {

                       Logger2.info("프로그램 INFO");

               }

               Logger2.warn("프로그램 WARN");

               Logger2.error("프로그램 ERROR");

               Logger2.fatal("프로그램 FATAL");

              

               // ROOT

               rootLogger.info("프로그램 끝");      

        }

}

 

[2] log4j.properties

 

## info 이상만 출력 허용 (debug Priority은 출력되지 않음)

## ROOT appender R 로 지정함

log4j.rootCategory=info, R

 

## com.search1 패키지의 로깅에는 warn 이상만 출력

## additivity = false 로 지정했으므로 log4j.search1.log 에만 출력됨

## additivity = true 로 지정하면 log4j.log, log4j.search1.log 모두에 출력됨

log4j.category.com.search1=warn, search1

log4j.additivity.com.search1=false

 

## com.search2 패키지의 로깅에는 info 이상만 출력

log4j.category.com.search2=info, search2

log4j.additivity.com.search2=false

 

## DailyRollingFileAppender 는 파일 교체주기를 월, , , 하루 2, 시간, 분 별로 정할수 있는 Appender

log4j.appender.R=org.apache.log4j.DailyRollingFileAppender

 

## priority 설정, 만약 Threshold=fatal 을 설정하면

## log4j.category.com.search1=warn, search1 를 설정했더라고 fatal 이상만 출력 된다.

log4j.appender.R.Threshold=debug

 

## ImmediateFlush 기본값은 true. 로그메세지들이 전혀 버퍼되지 않는 것을 의미

log4j.appender.R.ImmediateFlush=true

 

## log4j.log 파일에 출력 (디렉토리는 미리생성해 놓아야 에러 나지 않음)

log4j.appender.R.File=/study/log4j/log/log4j.log

 

## 기본값은 true이며 파일 끝에 추가하는 것을 의미한다.

## false 는 각각의 프로그램이 시작할때 파일에 덮어씌운다.

log4j.appender.R.Append=true

 

## 교체주기를 월, , , 하루 2, 시간, 분 별로 정할수 있다.

## 형식은 SimpleDateFormat 을 따른다. (":" 문자는 사용 금지)

log4j.appender.R.DatePattern='.'yyyyMMdd

 

## 패턴 : 날짜출력 Priority출력 클래스명출력 - 메시지출력 개행

log4j.appender.R.layout=org.apache.log4j.PatternLayout

log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c{2} %x - %m%n

 

log4j.appender.search1=org.apache.log4j.DailyRollingFileAppender

log4j.appender.search1.Threshold=debug

log4j.appender.search1.ImmediateFlush=true

log4j.appender.search1.File=/study/log4j/log/log4j.search1.log

log4j.appender.search1.Append=true

log4j.appender.search1.DatePattern='.'yyyyMMdd

log4j.appender.search1.layout=org.apache.log4j.PatternLayout

log4j.appender.search1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %m%n

              

log4j.appender.search2=org.apache.log4j.DailyRollingFileAppender

log4j.appender.search2.Threshold=debug

log4j.appender.search2.ImmediateFlush=true

log4j.appender.search2.File=/study/log4j/log/log4j.search2.log

log4j.appender.search2.Append=true

log4j.appender.search2.DatePattern='.'yyyyMMdd

log4j.appender.search2.layout=org.apache.log4j.PatternLayout

log4j.appender.search2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %m%n

 

[3] 결과

 

(1) log4j.log

        2006-01-02 16:29:35,984 INFO  root  - 프로그램 시작

        2006-01-02 16:29:35,984 INFO  root  - 프로그램 끝

 

(2) log4j.search1.log

        2006-01-02 16:29:35,984 프로그램 WARN

        2006-01-02 16:29:35,984 프로그램 ERROR

        2006-01-02 16:29:35,984 프로그램 FATAL

 

(3) log4j.search2.log

        2006-01-02 16:29:35,984 프로그램 INFO

        2006-01-02 16:29:35,984 프로그램 WARN

        2006-01-02 16:29:35,984 프로그램 ERROR

        2006-01-02 16:29:35,984 프로그램 FATAL

Log4j 상세 설명

org.apache.log4j.Logger 사용

 

n         Category extends 받은 Logger 클래스 사용

ü        org.apache.log4j.Logger extends org.apache.log4j.Category)

ü        Category.getInstance() 방식은 deprecated .
대신 Logger.getLogger() 방식으로 대체됨

 

      public static Logger getLogger(String name);

      public static Logger getLogger(Class clazz);

      public static Logger getRootLogger();

      public static Logger getLogger(String name, LoggerFactory factory);

 

주요 컴포넌트

 

n         Categories

n         appenders

ü        콘솔, 텍스트파일, html 파일, xml 파일, 소켓, Windows NT Event Log, 이메일 전송 가능

ü        ConsoleAppender, FileAppender, SMTPAppender, SocketAppender, NTEventLogAppender, SyslogAppender, JMSAppender, AsyncAppender, NullAppender

n         layouts : 메시지 형식

 

Priority(우선권)

 

      debug : 디버깅 메세지

      info : verbose 모드에서 출력될만한 메세지

      warn : 이상없이 계속 실행될 수 있는 정도의 경고메세지

      error : 그럭저럭 돌아갈만한 정도의 에러메세지

      fatal : 비정상적으로 종료될 치명적인 메시지

 

Appender 옵션

 

전체 옵션

log4j.configuration=app_config.properties

log4j.debug=true

log4j.disable=INFO

log4j.additivity.your.category.name=false

log4j.defaultInitOverride=false

log4j.disableOverride=false

ConsoleAppender

Threadhold=WARN

ImmediateFlush=true

Target=System.err

FileAppender

Threadhold=WARN

ImmediateFlush=true

File=mylog.txt

Append=false

RollingFileAppender

Threadhold=WARN

ImmediateFlush=true

File=mylog.txt

Append=false

MaxFileSize=100KB

MaxBackupIndex=2

DailyRollingFileAppender

Threadhold=WARN

ImmediateFlush=true

File=mylog.txt

Append=false

DatePattern='.'yyyy-ww

 

n         log4j.configuration=app_config.properties

ü        ex> java –Dlog4j.configuration= app_config.properties … 형식으로 속성 파일 설정

n         log4j.debug=true

ü        기본값은 false. log4j 를 설정하는 상세 정보를 출력

n         Log4j.disable=INFO

ü        모든 category에서 여기 지정한 priority 보다 같거나 낮은 priority 메세지는 로깅하지 않는다. (log4j.disableOverride=false 일때에만 동작)

n         log4j.additivity.your.category.name=false

ü        기본값은 true. appender ancestor(조상)으로부터 쌓이게 할지(true) 그렇게 하지 않을지(false)를 지정한다.

n         log4j.defaultInitOverride=false

ü        Category.getRoot() Category.getInstance(...) 메소드를 처음으로 호출하여   Log4j 의 초기화 과정을 마친다.("log4j.debug=true" 로 지정하여 초기화가 일어나는 것을 볼 수 있다) 초기화되는 동안 Log4j 는 어플리케이션의 클래스패스에서 "log4j.properties" 파일이나 "log4j.configuration=app_config.properties" 프로퍼티를 통해 지정한 파일을 찾는다. 만약 이것(프로퍼티를 통해 지정한 환경파일을 찾는 것)을 원하지 않는다면 이 프로퍼티를 true 로 세팅하라.

ü        이것을 시스템 property로 설정할 필요가 있다. 예를 들어 다음과 같이 프로그램을 구동한다. java -Dlog4j.defaultInitOverride=true ...   왜냐하면 설정파일에 세팅했다면 이미 너무 늦기 때문이다.Log4j는 이미 그 파일을 읽기위해 시작되었을 것이다.

n         log4j.disableOverride=false

ü        기본값은 false. 가끔 true로 설정하여 log.disable 프로퍼티를 무시할 수 있다.

n         Threadhold=WARN

ü        appender category priority가 더 낮게 지정되어 있다고 할지라도 여기 명시된 priority보다 낮은 메세지들을 로깅하지 않을 것이다. 이것은 콘솔에 모든 메세지가 나타나는 동안 파일에 로깅되는 경우와 같이 메세지의 숫자를 줄이는데 유용하다.

n         ImmediateFlush=true

ü        기본값은 true. 로그메세지들이 전혀 버퍼되지 않는 것을 의미하며 대부분의 상황에 적당하다.

n         Target=System.err

ü        기본값은 System.out

n         File=mylog.txt

ü        로깅할 파일명. 앞부분에 경로를 나타내기 위해 ${some_property_key} (예를 들어 java.home 또는 user.home 과 같은 시스템 프로퍼티)를 사용할 수 있다. 사실 모든 옵션들의 프로퍼티키들은 이런 종류의 값을 설정 가능하다.

n         Append=false

ü        기본값은 true이며 파일 끝에 추가하는 것을 의미한다. false 는 각각의 프로그램이 시작할때 파일에 덮어씌운다.

n         MaxFileSize=100KB

ü        끝에 KB, MB 또는 GB를 붙인다. 지정한 크기에 도달하면 로그파일을 교체한다(roll).

n         MaxBackupIndex=2

ü        최대 2()의 백업 파일들을 유지시킨다. 오래된 파일들은 삭제한다. 0 은 백업파일을 만들지 않는다.

n         DatePattern='.'yyyy-ww

ü        매주마다 파일을 교체(roll)한다. 교체주기를 월, , , 하루 2, 시간, 분 별로 정할수 있다. 이 값은 교체주기를 설정할 뿐만 아니라 백업파일의 붙는 문자열도 정한다.

ü        콜론(:) 문자를 값의 어디에도 사용하지 말라. 그것 말고는 자바의 SimpleDateFormat 의 어떤 형식 문자열을 사용할 수 있다. 특히 한쌍의 작은따옴표(single quote) 안에 있는 문자를 반드시 제어해주어야 한다.(예의 '.' 와 같이)

ü        '.'yyyy-MM: 매달의 첫날에 로그파일을 교체한다.

ü        '.'yyyy-ww: 매주의 첫날에 로그파일을 교체한다.

ü        '.'yyyy-MM-dd: 매일 자정에 로그파일을 교체한다.

ü        '.'yyyy-MM-dd-a: 매일 자정정오에 로그파일을 교체한다.

ü        '.'yyyy-MM-dd-HH: 시간마다(시간이 시작할때) 로그파일을 교체한다.

ü        '.'yyyy-MM-dd-HH-mm: 분마다(분이 시작할때) 로그파일을 교체한다.

 

layout 옵션

 

PatternLayout

ConversionPattern=%m%n

HTMLLayout

LocatoinInfo=true

Title=My app title

XMLLayout

LocatoinInfo=true

TTCCLayout

(이것 대신 더 유연한 PatternLayout을 사용하라)

DateFormat=ISO8601

TimeZoneID=GMT-8:00

CategoryPrefixing=false

ContextPrinting=false

ThreadPrinting=false

 

n         ConversionPattern

ü        %d{yyyy-MM-dd HH:mm:ss,SSS} : 날짜 출력 {} 내용은 SimpleDateFormat 형식을 따름

ü        %-5p : Priority 출력 (fatal, error, warn, info, debug)

ü        %n : 개행 문자 출력

ü        %t : 자바 스레드명 출력

ü        %F : 파일명출력

ü        %L : 라인넘버 출력

ü        %c{2} : 클래스명 출력.

예를 들어 category 이름이 "a.b.c" 일때 %c{2} "b.c"를 출력하며 {2}는 도트(.)로 구분된 category 이름의 마지막 두개의 컴포넌트를 의미한다. {n} 이 없으면 기본적으로 카테고리의 이름을 모두 출력한다.

ü        %x : 로깅이벤트를 발생시킨 스레드에 관련된 내포검사항목(Nested Diagnostic Context : NDC)을 출력한다.

ü        Java Servlet 과 같이 다수의 클라이언트가 분산된 스레드에 의해 다루어 질 때 유용하다.

ü        %m : 메시지 출력

ü        %r : 어플리케이션이 시작되어 로깅이벤트가 일어날때까지의 경과시간을 밀리세컨드 값으로 출력

ü        %% : 하나의 % 기호를 출력

ü        %l : 소스코드의 위치정보를 출력. %C. %M(%F:%L) 의 축약형

ü        %C : 호출자의 완전한 클래스이름을 출력. %C. %M(%F:%L) 의 축약형

ü        %M : 로깅요청을 일으킨 메소드를 출력

 

ü        필드 안에서 완쪽 정렬을 하기위해 마이너스 기호(-)를 사용

ü        %20c : 최소 20문자 공간에서 category 이름을 (기본적인)오른쪽 정렬

ü        %-20c : 최소 20문자 공간에서 category 이름을 왼쪽 정렬

ü        %.30c : 만약 category 이름이 30문자보다 길면 (앞에서부터)자른다. 최소폭이 없으므로 30문자보다 짧다고 해도 여백공간은 없다.

ü        %20.30c : category 이름이 20문자보다 짧으면 오른쪽 정렬을 하고, 30자보다 길면 시작부터 자른다.

ü        %-20.30c : category 이름이 20자보다 짧으면 왼쪽 정렬을 하고, 30자보다 길면 시작에서부터 자른다.

 

è [경고] 프로그램의 실행속도를 느리게 하는 옵션 : %d, %l, %C, %M, %F, %L

n         LocatoinInfo=true

ü        기본값은 false. 자바파일명과 행번호를 출력한다.

n         Title=My app title

ü        기본값은 Log4j Log Message. HTML <title>태그에 주어진다

n         DateFormat=ISO8601

ü        자바의 SimpleDateFormat 의 생성자이거나 NULL, RELATIVE, ABSOLUTE, DATE, ISO8601 중 하나.

n         TimeZoneID=GMT-8:00

ü        TimeZone.getTimeZone(java.lang.String) 메소드에 의해 나올만한 형식의 문자열

n         CategoryPrefixing=false

ü        기본값은 true. category 이름을 출력한다.

n         ContextPrinting=false

ü        기본값은 true. 현재 스레드에 속하는 내포검사항목 정보를 출력한다.

n         ThreadPrinting=false

ü        기본값은 true. 스레드명을 출력한다.

 

Log4j 참고 사항

성능

 

n         코드상에서 성능이 매우 중요한 곳에서는 로깅메소드의 파라미터를 만드는 시간을 절약하기 위해 다음과 같이 사용한다. (isDebugEnabled(), isInfoEnabled() 사용)

 

if (Logger.isDebugEnabled() {

    Logger.debug("debug code");

}

 

n         SimpleLayout을 사용하였거나 %p, %m, %n의 패턴만 사용하여 설정한 경우 System.out.println(...) 만큼 성능이 빠르다고 테스트됐다.

n         ConversionPattern 에서 프로그램의 실행속도를 느리게 하는 옵션 è %d, %l, %C, %M, %F, %L

 

내포검사항목(NDC) 사용

 

n         가끔 서블릿처럼 하나의 코드가 각각의 클라이언트를 서비스 하기위해 여러개의 스레드로 인스턴스화 되어 많은 클라이언트를 서비스한다. 이때 다른 클라이언트로 부터의 로깅 요청을 차별화하기 위해서 내포검사항목(NDC)를 사용할 수 있다. 할 수 있는 것은 로깅하기 전에 클라이언트의 고유한 정보를 NDC로 넣는다. 고유한 정보는 클라이언트의 IP주소, 호스트이름 또는 요청과 관련된 어떤 것도 될 수 있다. %x layout 패턴에 명시하면 요청한 로그 메세지에 그 문자열(고유한 정보)을 찍는다.

 

[NDC 사용 프로그램 예제 (Log4jTest.java)]

import org.apache.log4j.Logger;

import org.apache.log4j.NDC;

 

public class Log4jTest

{

        protected static final Logger logger = Logger.getLogger(Log4jTest.class);

 

        public static void main(String[] args)

        {

               //BasicConfigurator.configure();

              

               NDC.push("Client #45890");

 

               // ROOT

               Logger logger = Logger.getRootLogger();

               logger.info("프로그램 시작");

 

               switchNDC();

              

               // ROOT

               logger.info("프로그램 끝");  

        }

       

        static void switchNDC() {

               NDC.push("Client #99999");

               logger.info("프로그램 중간");

               NDC.pop();

        }

}

 

[NDC 사용 프로그램 예제 결과]

2006-01-02 18:02:11,984 INFO  root Client #45890 - 프로그램 시작

2006-01-02 18:02:11,984 INFO  Log4jTest Client #45890 Client #99999 - 프로그램 중간

2006-01-02 18:02:11,984 INFO  root Client #45890 - 프로그램 끝

 

기타 참고 사항

 

n         root category는 항상 지정된 priority가 있다.(기본값은 Priority.DEBUG),

n         일반적으로 Log4j 는 어플리케이션이 초기화되는 동안 보통 설정파일을 읽어들여 한번만 설정된다.

n         appender 들은 singleton 이 아니라 추가된다는 것을 주의하라. appender 로부터 물려받는 것을 불가능하게 하기 위해 category cat.setAdditivity(false) 메소드를 사용하라.  그러면 로그 메세지는 해당 category에 특별히 설정된 appender 로만 보내질 것이다.

n         정적 메소드인 BasicConfigurator.configure() 메소드는 System.out.println(...) 구문이 그러하듯 콘솔에 로깅한다. 이 메소드는 루트 category ConsoleAppender 를 붙여 콘솔에 프린트 하는 기능을 가지고 있다. 출력은 %-4r [%t] %-5p %c %x - %m%n 으로 세팅된 PatternLayout 을 사용하여 구성된다. 이 메소드는 log4j.properties 파일을 사용하는 것이 더 간단하고 유연하기 때문에 그다지 필요하지 않다.

n         log4j 를 설정하는 기본 파일은 log4j.properties 이다. 이 파일을 어플리케이션의 클래스패스에 지정된 어느곳이든 위치시킨다.

n         Java 프로퍼티 파일에서 설정 정보를 읽어오려면 정적메소드 중 하나인 PropertyConfigurator.configure(...) 메소드를 사용하라. 이미 설정되어 있는 설정은 지워지지도 재설정되지도 않는다. 이 메소드를 사용하려면 정적메소드인 BasicConfigurator.resetConfiguration() 메소드를 먼저 호출하라. 이 메소드 사용은 코드를 길고 복잡하게 할 수도 있다. 초보자는 각각의 어플리케이션의 루트디렉토리에 log4j.properties 파일 하나만 위치시켜라.

n         참고 사이트 : http://logging.apache.org/log4j/docs/

 

[]

2008. 9. 8. 15:06

MultipartRequest 로 파일 업로드 하기

파일을 업로드 한다는 것은 원격의 사용자가 서버 측으로 네트워크를 통해 파일을 전송하는 일이다<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

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

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

 

<Form action=receive.jsp Method=POST>

이름 : <Input type=TEXT name=userName> <BR>

<input type=SUBMIT value= >

</Form>


위의 파일을 실행하면 Action 태그에 정의된 페이지에서 사용자의 입력 값을 전송 받을 있게 된다. 하지만 File 경우는 그리 만만치 않다. 사용자가 입력하는 값은 Text 형태의 값이 대부분이고, 전송되는 File 형태는 Binary 타입이기 때문이다.

때문에 파일이 전송될 때에는 파일의 형태를 읽어 들일 있는 Servlet 또는 Java Bean 제작해야 한다.

 

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

 

위의 파일을 보면 enctype 이라는 태그가 데이터를 전송하게 타입을 지정하는 부분이다.

아래쪽의 Input type=FILE 이라는 부분은 파일을 선택할 있는 창이 뜨게 되는 부분이다.

 

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

그럼 데이터는 어떻게 받아낼까.

ServletRequest 인터페이스 에는 getInputStream() 이라는 메소드가 있다. 메소드는 클라이언트 측에서 전송되는 스트림을 서버측에서 받아줄 통로를 열어주는 메소드 이다. 위의 메소드를 통하여 사용자가 전송하는 스트림을 받아올 것이다.

아래는 데이터를 받아오는 receive.jsp 파일이다.

 

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

%>

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

 

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

 

 

 

 

 

 

 

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

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

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

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

 

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

 

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

 

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

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

MultipartRequest 파일 업로드 하기

위와 같은 복잡한 과정을 거쳐 업로드를 하게 된다면 자바 IO 제대로 공부하지 않은 사람은 업로드 게시판은 절대 꿈도 것이다. 하지만 이렇게 복잡한 업로드를 간단히 해결해 주는 클래스들이 인터넷 상에 제공되고 있다.

우리가 사용할 MultipartRequest 라는 업로드 컴포넌트는 Oreilly 사에서 제공하는 컴포넌트이며 컴포넌트를 사용할 때에는 저작권이 따른다는 것을 알고 있기를 바란다.

또한 컴포넌트를 사용하려면 Oreilly 책을 구입해야 한다고 명시하고 있다.

 

위의 컴포넌트를 받으려면 아래의 웹사이트를 방문하여야 한다.

http://servlets.com/cos/index.html

 

위의 주소로 접속을 하고 화면을 아래로 스크롤 하게 되면 압축파일이 있는 표를 만나게 되는데

날짜를 확인하고 제일 최신 버전을 다운로드 받으면 된다.

참고로 현재 최신 버전은 2002 11 05 판이다.

 

cos-05Nov2002.zip 같은 파일을 찾았다면 다운로드를 하고 적당한 곳에 압축을 푼다.

압축을 풀면 아래와 같은 디렉토리가 생기게 된다.



 


디렉토리의 구조는 아래와 같다.

classes 디렉토리는  MultipartRequest 클래스 들이 위치한 디렉토리 이다.

Doc 디렉토리는 MultipartRequest API Document 들어있는 디렉토리 이다

Lib 디렉토리는 MultipartRequest 클래스들을 압축하여 놓은 Library 디렉토리이다.

Src 디렉토리는 Source 디렉토리 이다.

upload.war 파일은 아카이브 라는 형태의 파일로서 이것을 webapps 놓고 톰캣을 Restart 하게 되면 해당 war 파일이 압축이 풀리며 바로 사용 가능한 상태로 되는 파일형식이다. 파일을 이용하여 테스트를 있다.

 

Lib 디렉터리에 있는 cos.jar 이라는 파일을 톰캣 설치디렉토리의 common/lib 복사 한다. (c:/tomcat4/common/lib)

common/lib 위치 시켜야 하는데 이유는 톰캣이 처음 시작될 common/lib 있는 라이브러리를 읽어 들일 있게 해당 파일을 로딩하기 때문이다. JDBC 드라이버도 마찬가지로 이곳에 위치시켜야 한다.

Tomcat restart 하게 되면 cos.jar 파일에 들어있는 클래스들을 이용할 있게 된다.

 

본격적으로 업로드를 해보자.

 

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

<%-- 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 부터 실행을 한다.

업로드 파일을 선택하고 전송 버튼을 누르게 되면 아래와 같은 그림이 나오게 된다.

 

 

 

 

 

 

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

 

 

 

 

 

이제 업로드 디렉터리를 보게 되면 아래와 같은 그림이 나오게 된다.

 

 

 

 

 

 

위의 결과치를 보게 되면 MultipartRequest 안에 들어있는 가지의 메소드의 용법을 있다.

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

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

 

getFilesystemName() 메소드는 서버측으로 실제 업로드 파일의 이름을 얻어오는 메소드 라는 것을 수가 있다.

getOriginalFileName() 메소드는 사용자가 업로드 실제 파일 이름을 얻어오는 메소드 이다.

그리고 중복 파일이 있을 경우에는 자동으로 파일이름 뒤에 중복된 숫자가 붙는다는 것을 있다.

이제 이렇게 업로드 파일의 이름을 데이터베이스에 입력을 하게 되면 자료실을 쉽게 구현 수가 있게 된다.

 

다음으로 알아볼 것은 업로드 파일의 사이즈를 알아내는 부분이다.

MultipartRequest 에는 파일의 사이즈를 반납해 주는 메소드는 없다. 하지만 File 객체 자체를 반납해 주는 메소드가 존재한다.

실제 파일객체를 받게 경우 File 객체에서 사용할 있는 모든 메소드를 사용할 있다는 장점이 있다.

파일의 사이즈는 아래와 같이 얻어오면 된다.

File f = multi.getFile("userFile");

같이 받아오면 된다.  이제 이렇게 받아온 파일을 통해 파일의 사이즈 각종 정보를 얻을 있게 된다.

 

 

아래의 코드를 receive.jsp 파일에 추가한다. 위치는 userFile 이름을 받아오는 아랫쪽에 위치 시키면 된다.

File f = multi.getFile(userFile);

int fileSize = (int)file.length();

out.print(<BR> 파일 사이즈 : + fileSize + <BR>);

사이즈가 출력이 되는 것을 있을 것이다. 참고로 int 형변환 하는 것은 File 객체의 length() 메소드의 반환값이 long 이기 때문에 형변환을 해준 것이다.

 

이제 여러 개의 파일을 업로드를 해보자. 이렇게 업로드 파일을 데이터 베이스의 테이블에 저장해 보도록 하자.

테이블의 구조는 아래와 같다. MySQL test 데이터베이스에 만들도록 하자.

 

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>

 

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

이제 위의 HTML 폼에서 넘어가는 파일들과 파라메터들을 받아서 저장해줄 JSP 파일이 필요하다.

아래의 파일이 역할을 해주는 파일이다.

) 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"; // 업로드 경로

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

             */

            

             // 넘어오는 파라메터.

             String userName = multi.getParameter("userName");

             String subject = multi.getParameter("subject");

             String contents = multi.getParameter("contents");

            

             // 넘어오는 파일 이름

             String fileName1 = multi.getFilesystemName("up1");

             String fileName2 = multi.getFilesystemName("up2");

             String fileName3 = multi.getFilesystemName("up3");

 

             // 파일  사이즈 받기

             int size1 = (int)(new File(savePath + "/" + fileName1).length());

             int size2 = (int)(new File(savePath + "/" + fileName2).length());

             int size3 = (int)(new File(savePath + "/" + fileName3).length());

            

             // 데이터베이스 접속

             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");

             }

%>

 

위의 파일을 보게 되면 넘어오는 파라메터를 request 객체로 받지 않고 request MultipartRequest 매개변수로 넘겨준 MultipartRequest 인스턴스인 multi 받아낸다는 것을 있다.

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

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

 

파일의 사이즈를 받는 부분은 파일을 생성하고 그곳에 length() 메소드를 호출하여 int 형변환 하였다는 것을 있다.

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

 

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

데이터베이스에 저장할 때는 파일의 이름과 파일의 사이즈를 입력해주면 된다.

위에서 받아온 파일의 이름을 PreparedStatement IN 파라메터에 각각 대입을 해주고 executeUpdate 숫자를 받아주면 데이터베이스에 입력이 되었는가의 판단 여부를 알아 있다. 만약 데이터베이스에 입력이 되었다면 1 반환될 것이고 그렇지 않다면 0 반납이 되기 때문이다. 이렇게 나온 숫자를 이용하여 데이터 베이스에 입력이 안되었다면 기존의 업로드 파일들을 지워줘야 한다.

 

MultipartRequest 클래스의 메소드 중에는 파일입력 파라메터들의 이름을 Enumeration 객체로 반납해 주는 메소드가 있다.

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

이렇게 알게 파일의 실제 이름을 File 객체로 생성하여 delete() 메소드를 호출하게 되면 업로드 파일이 서버측에서 삭제되게 된다.

 

만약 데이터베이스에 입력이 되었다면 upList.jsp 파일로 요청이 넘어가게 되는데 upList.jsp 파일에서는 데이터베이스에 입력되어 있는 모든 레코드를 num 순서의 역방향(desc) 정렬하여 사용자 측에 보여주게 된다.

아래의 그림은 upList.jsp 파일이다. 제목을 클릭하면 업로드된 게시물의 내용과 업로드 파일을 수가 있다.

 

그림 . upList.jsp

 

 

 

 

                       

 

그럼 데이터 베이스에는 어떻게 들어가 있는지 보자.

MySQL 서버가 깔려있는 경로로 이동하여 mysql u root p test 라고 입력한 패스워드를 입력한다.

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

 

 

 

 

 

 

 

아래는 upList.jsp 파일의 소스이다.

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

 

<%

             // 데이터베이스 접속

             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 그림과 같이 보인다면 제목을 클릭해 보자. upView.jsp 페이지가 이동되는 것을 있다.

이제 upView.jsp 에서 해야 일이 머릿속에 그려질 것이다.

먼저 해야 일은 upList.jsp  에서 넘어오는 파라메터의 값을 받아내야 한다.

num 값을 이용하여 쿼리를 전송하고 그렇게 얻어지는 결과치를 브라우져에 알맞게 뿌려주면 된다.

또한 파일들에 대하여 링크를 걸어줘야 파일을 클라이언트 측에서 인식을 수가 있게 된다.

현재는 파일에 대해 파일이름을 직접 지정하지만 추후 제작할 업로드 게시판에서는 다운로드를 해주는 파일을 제작할 것이다.

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

 

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

             // 데이터베이스 접속

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

%>

 

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

 

 

  

화면 하단에 보면 수정/삭제 부분이 보인다. 여기서 수정이란 기존의 파일을 삭제하고 새로운 파일을 올리겠다는 것이고

삭제는 기존의 파일과 데이터베이스에 들어있는 정보를 같이 삭제 하겠다는 것이다.

 

그럼 삭제를 먼저 해보자. 위의 그림에서 보이는 것과 같이 삭제 라는 곳에 마우스를 올리고 브라우져 하단에 나오는 링크정보를 보도록 하자 delete.jsp?num=1 같이 정보가 넘어가는 것을 있다.

delete.jsp  파일에서는 넘어오는 파라메터를 이용하여 데이터베이스에 쿼리를 하고 얻어진 파일이름을 이용하여 파일을 삭제하고 다시 데이터베이스의 레코드를 삭제하면 된다.  , 정보가 삭제되었다면 다시 upList.jsp 파일로 페이지를 이동시켜주면 된다.

아래의 예제를 작성한 실행 보고 윈도우탐색기에서 파일이 삭제 되었는지 보고, 데이터베이스에서는 레코드가 삭제 되었는지 확인해 보자.

 

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

%>

 

위의 파일에서는 ResultSet 에서 나오는 테이블 정보를 이용하여(ResultSetMetaData) 선택된 컬럼의 개수를 알아내고, 그렇게 알아낸 컬럼의 숫자만큼 순환문을 돌면서 파일객체를 생성하여 업로드 파일을 삭제 하는 것을 있다.

이후 두번째 쿼리문 에서는 해당 레코드를 삭제하는 쿼리를 데이터베이스에 전송한 다는 것을 있다.

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

 

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

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

수정을 하려면 새로운 내용과 새로운 파일을 입력을 받을 있는 HTML 폼이 필요하다. 이곳에서 넘어가는 파라메터들에 대하여 작업을 해야 JSP 파일도 필요하다.

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

 

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

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

 

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

 

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

%>

 

위의 예제에서 보면 쿼리문장을 순환문을 통해 작성을 한다는 것을 수가 있다.

이는 사용자가 새로 갱신될 파일이나 내용을 어떻게 전송할 예측할 수가 없기 때문에 순환문을 통해 실제 업로드 파라메터에 해당하는 부분만 쿼리 문장에 포함을 시키려고 것이다.

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

출처 : Tong - 훈스구락부님의 JAVA/JSP통

 
2008. 9. 8. 15:02

JSP: 파일 업로드 (cos.jar 이용) MultipartRequest를 통한 FIle Upload, Download, Delete

파일 업로드 (cos.jar 이용)

바운더리를 이용한 방법은 복잡하다. 그래서 기존의 방법을 사용하는 방법으로 다시 파일 업로드를 짜보겠다.


//upload.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>파일업로드</title>
</head>
<body>
<h3>파일 업로드</h3>
업로드한 파일을 선택해 주세요.<br>
<form action="upload.jsp" method="post" enctype="multipart/form-data">
<table>
<tr>
 <td>제목</td>
 <td><input type="text" name="subject"></td>
</tr>
<tr>
 <td>파일 이름</td>
 <td><input type ="file" name="file1"></td>
</tr>
<tr>
 <td>파일 이름</td>
 <td><input type ="file" name="file2"></td>
</tr>
<tr>
 <td colspan="2">
 <input type="submit">
 <input type="reset">
 </td>
</tr>
</table>
</body>
</html>



파일 업로드

업로드한 파일을 선택해 주세요.
<FORM action=upload.jsp method=post encType=multipart/form-data>

제목 <INPUT value=파일업로드 name=subject>
파일 이름 <INPUT type=file name=file1>
파일 이름 <INPUT type=file name=file2>
<INPUT type=submit value="쿼리 전송"> <INPUT type=reset value=원래대로>
</FORM>


//upload.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
 pageEncoding="EUC-KR"%>
<%@ page import="java.io.*" %>
<%@ page import="com.oreilly.servlet.*" %>
<%@ page import="com.oreilly.servlet.multipart.*" %>
<% request.setCharacterEncoding("euc-kr"); %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>파일 업로드 결과</title>
</head>
<body>
<h3>파일 업로드 결과</h3>
<%
 String dir = application.getRealPath("/upload"); //폴더 얻기
 int max = 5 * 1024 * 1024; //최대 업로드 크기는 5M까지만 허용
 try {
  MultipartRequest m = new MultipartRequest(request, dir, max, "euc-kr",new DefaultFileRenamePolicy());
  String subject = m.getParameter("subject");
  String file1 = m.getFilesystemName("file1");
  String ofile1 = m.getOriginalFileName("file1");
 
  String file2 = m.getFilesystemName("file2");
  String ofile2 = m.getOriginalFileName("file2");
%>
<%  
  if(file1 != null) {
%>
  업로드 파일1:<a href=/upload/<%=file1%>><%=ofile1%></a><br>
<%
  }//if
 
  if(file2 != null) {
%>
  업로드 파일2:<a href=/upload/<%=file2%>><%=ofile2%></a><br>
<%
  }//if
 }catch(Exception e){
  e.printStackTrace(new PrintWriter(out));
 }//catch
%>
</body>
</html>


파일 업로드 결과

업로드 파일1:hi.txt
업로드 파일2:sleeping.jpeg

파일저장장소는


C:\eclipse\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\webapps\ch1_web\upload


최신 다운로드

http://www.servlets.com/cos/













======================================================================================================================

======================================================================================================================



















[cos]MultipartRequest를 이용한 업로드 etc lib

2007/02/05 12:43

http://blog.naver.com/mangchi0909/40034081389

출처:http://aboutjsp.com

★ MultipartRequest를 이용하여 업로드구현하기

 


* 강좌를 시작하기전에....

- 기존의 jspSmartUpload를 대체해 가고 있는 MultipartRequest에 대한 간단한 사용법에 대해 강의 합니다.
JSP만을 사용하는 강좌이며 Beans, Servlet은 다루지 않습니다.

- MultipartRequest는 COS 패키지에 포함되어 있는 파일 업로드 컴포넌트 입니다.

- COS 에서는 한글등(non-Latin-1)의 언어를 지원하지 않았었습니다. 그러한 이유로 이아스(이창신)님 께서 배포한 COSI(COS International) 를 주로 사용 하였으나, 이아스님의 노력에 힘입어 2002년 5월 9일 자 COS에서는 한글을 포함한 non-Latin-1 계열의 언어를 지원하게 되었습니다. 근 2년간의 국제화를 위한 투쟁이 비로서 결실을 맺는 순간이었습니다.
이에 따라 본 강좌의 내용도 COS 맞추어 약간의 수정을 했습니다.

COS 공식 사이트 : http://www.servlets.com/cos/index.html


* MultipartRequest는....

필자는 기존에 jspSmartUpload를 주로 사용하여 업로드를 구현했었다. 하지만 jspSmartUpload는 로직자체에 상당한 문제점(업로드된 파일을 메모리에 올리고 작업하여 그로인해 파생되는 문제점들)이 있음이 밝혀 졌고, 그로인해 jspSmartUpload의 사용은 급속히 줄어 들었다.

사실 jspSmartUpload에서는 편리한 많은 메소드를 지원해주고 있어 MultipartRequest를 사용하는것 보다 훨씬 쉽게 원하는 기능을 구현 할수 있는 것이 사실이다. 하지만 jspSmartUpload는 문제점이 발견 되었으므로 가능한사용을 자제하는 것이 좋겠다.

MultipartRequest는 아주 간단한 메소드를 몇개 지원한다. 하지만 이 메소드들 만으로도 왠만한 기능은 전부 구현이 가능하니 실망하지 말자. getFile() 메소드를 이용하면 java.io.File 객체를 얻어 낼수 있으니 이를 이용하면 될것이다.


* 설치하기

MultipartRequest는 oreilly에서 배포하며, http://www.servlets.com/cos/index.html에서 다운로드 받아도 되고, 필자의 홈페이지(http://aboutjsp.com/)의 자료실에도 업로드를 해놓았으니 다운받아 사용해 보기 바란다.

설치 하는 방법은 다운로드 받아서 압축을 푼뒤, classes 디렉토리 아래를 톰캣의 classes 디렉토리에 통째로 복사한다. (예.ROOT/WEB-INF/classes) 혹은 cos.jar를 lib에 복사해도 된다.

COS 패키지기에는 MultipartRequest 말고도 유용한 많은 클래스들이 많이 존재하므로, 여기의 API문서를 참고하여 사용하기 바란다


* 업로드 구현

간단한 예제를 통해서 알아 보도록 하자.

wirte.htm

<html>
  <body>
    <form action="up.jsp" enctype="multipart/form-data" method="post">
      이름 : <input type="text" name="userName"> <BR>
      파일 : <input type="file" name="upfile">
      <input type="submit" value="Upload">
    </form>
  </body>
</html>

up.jsp

<%@ page contentType="text/html;charset=euc-kr" %>

<%@ page import="com.oreilly.servlet.MultipartRequest,

                   com.oreilly.servlet.multipart.DefaultFileRenamePolicy,
                   java.util.*" %>

<%
String savePath="/usr/local/tomcat/webapps/ROOT/test/upload"; // 저장할 디렉토리 (절대경로)

int sizeLimit = 5 * 1024 * 1024 ; // 5메가까지 제한 넘어서면 예외발생

try{
                MultipartRequest multi=new MultipartRequest(request, savePath, sizeLimit, new DefaultFileRenamePolicy());
                Enumeration formNames=multi.getFileNames(); // 폼의 이름 반환
                String formName=(String)formNames.nextElement(); // 자료가 많을 경우엔 while 문을 사용
                String fileName=multi.getFilesystemName(formName); // 파일의 이름 얻기

                if(fileName == null) {   // 파일이 업로드 되지 않았을때
                                out.print("파일 업로드 되지 않았음");
                } else {  // 파일이 업로드 되었을때
                                fileName=new String(fileName.getBytes("8859_1"),"euc-kr"); // 한글인코딩 - 브라우져에 출력
                                out.print("User Name : " + multi.getParameter("userName")  + "<BR>");
                                out.print("Form Name : " + formName + "<BR>");
                                out.print("File Name  : " + fileName);
                } // end if

 } catch(Exception e) {
                out.print("예외 상황 발생..! ");
}
%>



위의 예제 소스를 보면 대부분이 이해가 잘 갈것이라 생각되지만.. 하나씩 살펴 보도록 하겠다. 우선 write.htm 에서는 폼에서 method="post" 형식으로 해야 하며 ecntype="multipart/form-data" 를 꼭 붙여 주어야 한다.

다음으로 up.jsp를 하나 하나 살펴 보자. MultipartRequest 클래스를 import 하고, java.util.* 는Enumeration 객체를 사용하기 위해서 import 한다..

savePath 는 저장될 실제 디렉토리(시스템상의 절대 경로)를 적으면 된다. sizeLimit 에서는 제한 용량을 셋팅하는데, 위와같은방법으로 메가바이트 단위로 지정할 수 있다.

그 다음줄에서는 MultipartRequest 객체가 생성됨과 동시에 업로드가 이루어져 지정한 디렉토리에 저장된다. 이때 MultipartRequest의 여러 생성자들중 하나를 이용하면 되는데, 기존에는 새성자로 한글 "euc-kr"을 줬어야 했는데, 어쩐일인지 이제는 주지 않아아 한글 이름의 파일이 잘 저장되느는 것을 볼수 있다. 또한 가장 오른쪽의 'new DefaultFileRenamePolicy' 는 는 파일 이름 중복처리에 관한 것으로 넣을수도 있고, 뺄수도 있다. 필요하지 않다고 생각된다면 빼버리도록 하자.

그아래에 if 문을 보면, 파일이 업로드 되었을때와 업로드 되지 않았을때의 처리를 나누어서 할수 있도록 하고 있다.

if 문 위의 3라인은 파일의 이름을 얻기위한 로직으로 Enumeration 객체로 받은 폼의 이름을 이용하고 있다. 만약 폼이 여러개가 있을 경우엔 적절한 자료형을 이용하여 폼의 이름을 통해서 파일의 이름들을 얻어 낼수 있을 것이다. 만약 파일 업로드를 Beans로 구현할 경우엔 반드시 이러한 로직을(Enumeration 객체를 이용한 loop구문)사용해야 할 것이다.

사실 위의 예제에서는 굳이 Enumerration 객체를 가지고 구현할 필요는 없지만, 해당 메소드의 사용법을 보여주기 위해서 사용하였다. 이러한 방법을 사용하지 않을 경우에는 if 위에 3라인을 삭제하고 아래의 내용을 추가 하면다.

String fileName=multi.getFilesystemName("upfile");


* FileRenamePolicy 에 관해서...

이번 버젼의 MultipartRequest 에서 부터는 파일 중복처리 인터페이스가 추가 되었고, 위의 예제 소스는 그러한 내용이 반영되어있다. DefaultFileRenamePolicy는 FileRenamePolicy Interface 를 구현한 것으로, 중복된 파일 이름뒤에 숫자를 붙여 주고 있다. ( abcd.zip , abcd1.zip, abcd2.zip, abcd3.zip ....... )

DefaultFileRenamePolicy Class를 바탕으로 새로운 RenamePolicy class 를 만들면 자신이 원하는 FileRenamePolicy 를 적용할수 있다.

또한 getFilesystemName()메소드를 이용하여 변경된 파일 이름을 얻을수 있고, getOriginalFileName()메소드는 변경되기 이전의 파일이름을 넘겨준다.


* multi.getParameter()

write.htm 에서 서정한바와 같이 enctype="multipart/form-data" 로 지정하면, request.getParameter()로는 아무러 값도 받아 올수가 없게된다. 그러한 이유로 대부분의 파일업로드 컴포넌트에서는 getParameter() 메소드를 지원하는데, MultipartRequest에서도 이러한 메소드를 지원한다. 지원하는 메소드는 아래와 같으며, 사용법은 request.getParameter() 등과 동일하다.

String getParameter(String name)
Enumeration getParameterNames()
String[] getParameterValues(String name)


* 한글관련 문제 처리법

MultipartRequest multi=new MultipartRequest(request, savePath, sizeLimit, new DefaultFileRenamePolicy());

위를 아래와 같이 수정한다.

MultipartRequest multi=new MultipartRequest(request, savePath, sizeLimit, "euc-kr", new DefaultFileRenamePolicy());

"euc-kr" 부분엔 "ksc5601", "ms949" 등 자신의 환경에 알맞는 캐릭터셋을 넣어 주면 된다.

각 메소드들에 대한 자세한 사용법은 아래의 API문서를 참고 하기 바란다.

http://aboutjsp.com/docs/cos/












=====================================================================================================================

======================================================================================================================











MultipartRequest를 통한 FIle Upload, Download, Delete Java

2006/12/21 16:14

http://blog.naver.com/nije1983/130012485962

1. File Upload

MultipartRequest multi = null;
   String savepath = request.getRealPath("/") + "WebContent/StyleUpload";

   int limitSize = 15 * 1024 * 1024;
   
   try {
    multi = new MultipartRequest(request, savepath, limitSize, "euc-kr",

                                              new DefaultFileRenamePolicy());
    task = multi.getParameter("task");
    String styleNo = multi.getParameter("styleNo");
    String contents = multi.getParameter("contents");
    String attachFile = multi.getFilesystemName("attachFile");

   
    if (attachFile == null) {
     attachFile = "";
    } else {
     byte[] byteStr = attachFile.getBytes(); 
     int len = byteStr.length;
     if (len > 50) {
      File f = new File(savepath + "/" + attachFile);
      if (f.isFile()) {
       f.delete();
      }
     }
    }

} catch (IOException ie) {
    log.debug("첨부파일 용량 초과!!! 예외발생!!!");
    throw ie;
   }


2.File DownLoad

if(vo.getString("fileDown").equals("true")) {
          request.setCharacterEncoding("EUC-KR");
       String fileName = new String(request.getParameter("fileUrl").getBytes("ISO-8859-1"), "KSC5601");
       String fileUrl = "WebContent/StyleUpload/" + fileName;
       if(fileUrl == null) return;
       boolean fileexists = true;
       try {
        ServletContext cxt = getServletConfig().getServletContext();
        String file = cxt.getRealPath(fileUrl);
        File fileEx = new File(file);
        if(fileEx.exists()) {
           response.setContentType("application/octet-stream");
           response.setHeader("Content-Disposition","attachment; filename="+ java.net.URLEncoder.encode(fileName,"UTF-8"));
           byte [] buffer = new byte[1024*15];
           ServletOutputStream out = response.getOutputStream();
           BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
           BufferedOutputStream bout = new BufferedOutputStream(out);
           int n = 0;
           while((n=in.read(buffer, 0, 1024*15)) != -1) {
                 bout.write(buffer, 0, n);
           bout.flush();
           }
           bout.close();
           in.close();
           } else {
           fileexists = false;
           }
       } catch(Exception e) {
          e.printStackTrace();
          }
          if(!fileexists) {
           vo.put("message", MessageUtil.getMessage("MSG00009"));
          }

      }


3.File Delete

request.setCharacterEncoding("EUC-KR");
      String fileName = new String(request.getParameter("fileUrl").getBytes("ISO-8859-1"), "KSC5601");
      String fileUrl = "WebContent/StyleUpload/" + fileName;
      if(fileUrl == null) return;
      boolean fileexists = true;
      try
      {
       ServletContext cxt = getServletConfig().getServletContext();
       String file = cxt.getRealPath(fileUrl);
       File fileEx = new File(file);
       if(fileEx.exists())
       {
        fileEx.delete();
       }
      }
      catch(Exception e)
      {
          e.printStackTrace();
       }













=============================================================================================================

==============================================================================================================













파일 업로드하기(cos.jar사용) J2EE

2006/02/20 02:07

http://blog.naver.com/inwarde/80021997584

FileSelect-inwarde.jsp
ViewPage-inwarde.jsp

업로드 컴포넌트로는 cos.jar를 사용하여 간단한 웹 업로드 소스를 만들어 보았습니당...

cos.jar를 사용하기 위해서는 이것을 설정해 주어야 합니다.

이 파일은 http://www.servlets.com/에서 다운로드 받을 수 있습니다.

com.oreilly.servlet링크안에 cos-27May2002.zip 파일이 있습니다.

이 안에 cos.jar파일을 찾아서 클래스 패스를 잡아주거나 , 직접 톰켓안의 웹어플리케이션/WEB-INF/lib폴더 안에 설정을 해줍니다(톰켓4.x에서는 외부클래스패스의 이용을 제한하였기 때문에 사용하는 방법).



먼저 파일 업로드를 위한 폼형태는


<form enctype="multipart/form-data">

   <input type="file" name="xxxx">

</form>


입니다.

파일 업로드 창을 만들기 위해서 input type에 file태그를 만들고

이것을 전송하기 위해서 enctype태그를 사용하였습니다.


다음으로

업로드를 하고 데이터를 분석하는 jsp페이지를 만들어 봅시다.

com/oreilly/servlet 안의 MultipartRequest클래스를 사용합니다.

이 객체를 생성하면 지정한 파일이 서버상의 폴더에 저장 됩니다.

생성자

MultipartRequest AAA = new MultipartRequset(

                                         HttpServletRequest request,

                                         String saveDirectory,

                                         int maxPostSize,

                                         String encoding,

                                         FileRenamePolicy policy)


파라미터 이름 추출          Enumeration params = AAA.getParameterNames();

파라미터 이름을 통한 값 추출     String paramValue = AAA.getParameter(String name);

파일속성 파라미터 이름 추출      Enumeration files = AAA.getFileNames();

파일 이름 추출(저장된값)          String fileName = AAA.getFilesystemName(name);

파일 이름 추출(원래값)             String original = AAA.getOriginalFileName(name);

컨텐트타입 반환                       String type = AAA.getContentType(name);

파일 객체 반환                         File file = AAA.getFile(name);


출처 : Tong - 훈스구락부님의 JAVA/JSP통

'My work space > JSP/Servlet' 카테고리의 다른 글

Log4j 사용법 로깅-Log4J  (0) 2008.09.08
MultipartRequest 로 파일 업로드 하기  (0) 2008.09.08
Servlet API 파일  (0) 2008.09.08
session사용  (0) 2008.09.08
세션설정,세션에서 값 가져오기  (0) 2008.09.08
2008. 9. 8. 14:59

Servlet API 파일

2008. 9. 8. 14:58

session사용

세션


아이디와 패스워드를 넣고 로긴을 하면 웹페이지를 종료시키지 않은 이상

계속 로그인 상태로 웹서핑을 하는데 비접속자와 구분을 위해 꼭 필요하다.


진짜 구식 방법으로 모든 웹페이지에 아이디 정보를 넘겨주는 방법도 있지만

세션에 저장하게 되면 간단하게 어느 웹페이지에서나

한줄의 명령어로 아이디를 불러와서 개인정보도 불러올 수 있게 된다.



* 세션의 사용 *


┌───────────┬────────────────────────────┐

│                                 │      session.setAttribute("mySession", "session value");    

│        세션의 생성         ├────────────────────────────┤

│                                 │     mySession이란 이름을 가진 세션에 session value란       │

│                                 │     값을 설정한다.                                                           │

├───────────┼────────────────────────────┤

│                                 │      session.setMaxInactiveInterval(60*5);                         │

│   세션의 유지기간 설정 ├────────────────────────────┤

│                                 │       세션 유지기간을 5분을 설정하여 사용자가 5분동안         │

│                                 │      아무런 동작이 없는 경우 세션은 자동으로 종료가 된다.    │

├───────────┼────────────────────────────┤

│                                 │        session.removeAttribute("mySession");                     │

│        세션속성삭제       ├────────────────────────────┤

│                                 │      mySession  이라는 이름의 세션값을 삭제한다.               │

├───────────┼────────────────────────────┤

│                                 │       session.invalidate();                                                │

│          세션삭제           ├────────────────────────────┤

│                                 │        세션값을 삭제한다.                                                  │

└───────────┴────────────────────────────┘



로그인과 결합된 세션사용방법을 알아보자.



아  이 디   :   miojj

패스워드   :   1234


입력을 누르면 자료는 디비와 접속하여 비교분석을 하게되고

회원이라는 등식이 성립되면 변수 myId 로 반환하게 만든다.


session.setAttribute("memID", myId); <- memID 라는 세션명으로 저장하면



웹페이지가 살아있는 동안 또는 유지기간내에


 <%String memberId = (String)session.getAttribute("memID");%>


getAttribute 로 꺼내서 사용할 수 있다.  이 때 세션이름 사용


* 세션저장시 세션명을 달리하면 여러개의 세션도 저장이 된다. *



그럼 여기서 로그인 구성의 마무리 로그아웃은

당연히  <% session.invalidate(); %> 로 싹 지워버리자.

그리고 스크립트로  alert!("로그아웃 되었습니다."); 을 뿌려주는 쎈스!

 
2008. 9. 8. 14:57

세션설정,세션에서 값 가져오기

세션설정
세션 값을 설정하기 위해서는 setAttribute(String key, Object value) 메소드를 사용한다. 여기서 key는 String 형으로 지정하지만, 값은 Object 형으로 지정하기 때문에 일반적으로 많이 사용하는 String 뿐만 아니라, 프로그램에서 사용하고 있던 객체(Object)를 세션으로 설정할 수도 있다.

session.setAttribute("id", "gildong");  // 문자열을 값으로 설정
Hashtable h = new Hashtable();  // 해쉬테이블을 값으로 설절
h.put("id"  , "gildong");
h.put("name", "홍길동");
h.put("tel" , "011-673-9335");
session.setAttribute("user", h);


세션에서 값 가져오기
JSP 웹 페이지에서 세션 값을 가져오기 위해서는 getAttribute(String key) 메소드를 사용한다. 여기서 주의해야 할 점으로는 세션의 값이 Object 형으로 저장되기 때문에 반환되는 데이터의 형도 동일하게 Object 형이된다. 따라서, 리턴 받고자 하는 데이터형으로 캐스팅(Casting)을 해 주어야 한다.

String    id = (String)    session.getAttribute("id");
Hashtable h  = (Hashtable) session.getAttribute("user");

위의 ①에서 해쉬테이블을 세션으로 설정한 후 세션에서 값을 가져오는 예를 getSession.jsp 프로그램으로 구현하면 다음과 같다.


세션에서 사용하는 주요 메소드
앞에서 살펴본 session 객체는 javax.servlet.http.HttpSession 인터페이스로 구현되어 있으며, setAttribute() 와 getAttribute() 외에더 다음과 같은 여러 가지의 메소드를 제공하고 있다.

public Object getAttribute(String key)
세션에 들어 있는 값중에서 key에 해당하는 값을 가져오며, 값이 없을 경우 null을 리턴한다. 리턴하는 데이터형이 Object이므로 String이나 Hashtable 등으로 캐스팅해서 사용해야 한다.

public void setAttribute(String key, Object value)
문자열로 지정되는 key 값에 해당하는 세션 값을 Object 형으로 설정한다.

public void removeAttribute(String key)
세션중에서 key에 해당하는 값을 제거한다.

public Enumeration getAttributeNames()
세션으로 설정되어 있는 모든 키를 java.util.* 에 포함되어 있는 Enumberation 형태로 가져온다. 따라서, 이 메소드를 사용하기 위해서는 page 지시부에 java.util.*를 import! 한 후 사용해야 한다.

public String getId()
세션이 열리면 각 세션에 대해서 고유한 ID가 할당되는데, 이 아이디를 문자열로 리턴한다.

public long getCreationTime()
세션이 처음 생성된 시간을 밀리 초로 계산하여 long형 정수로 리턴하며, 기준은 70년1월1일 00시 00분 00초이다.

public long getLastAccessedTime()
세션에 클라이언트가 마지막으로 request를 보낸 시간을 long 형으로 리턴한다.

public int getMaxInactiveInterval()
클라이언트의 요구가 없을 때 서버가 현재의 세션을 언제까지 유지할지를 정수로 리턴하며, 디폴트로는 30분으로 지정되어 있다.

public void invalidate()
현재의 세션을 모두 제거하므로, 세션의 속성값들이 자동적으로 상실된다.

public boolean isNew()
서버측에서 새로운 session객체를 생성하고 아직 클라이언트에게 세션ID를 할당하지 않은 경우 true를 리턴하고 기존의 세션이 유지되고 있는 상태라면 false를 리턴한다.

public void setMaxInactiveInterval(int seconds)
세션이 유지되는 시간을 밀리 초 단위로 설정하는 것으로서, 이 시간동안 클라이언트의 요청이 없으면 세션은 제거된다.

'My work space > JSP/Servlet' 카테고리의 다른 글

Servlet API 파일  (0) 2008.09.08
session사용  (0) 2008.09.08
session.setAttribute 에서 주의할 점  (0) 2008.09.08
request 객체  (0) 2008.09.08
request.getAttribute  (0) 2008.09.08
2008. 9. 8. 14:57

session.setAttribute 에서 주의할 점

protected void doPost(HttpServletRequest req, HttpServletResponse res)
                                        throws ServletException, IOException {
                                         
        HttpSession session = req.getSession(true);
        int total = 0;
        int robot1 = 1;
        int lego1 = 1;
        total = robot1+lego1;
       
        if(session.isNew()){
         session.setAttribute("imdi", total);
         session.setAttribute("robot", new int[] {0});
         session.setAttribute("lego", new int[]{0});
        }            

--> int type 을 그대로 입력하면 에러!

 

   HttpSession session = req.getSession(true);
        int total = 0;
        int robot1 = 1;
        int lego1 = 1;
        total = robot1+lego1;
       
        if(session.isNew()){
         Integer itotal = new Integer(total);
         // 형변환이 반드시 이루어져야함
         // Session 는 object 형만 가능하다.
         session.setAttribute("imdi", itotal);
         session.setAttribute("robot", new int[] {0});
         session.setAttribute("lego", new int[]{0});
        }    

'My work space > JSP/Servlet' 카테고리의 다른 글

session사용  (0) 2008.09.08
세션설정,세션에서 값 가져오기  (0) 2008.09.08
request 객체  (0) 2008.09.08
request.getAttribute  (0) 2008.09.08
jsp/Servlet 기본2  (0) 2008.09.08
2008. 9. 8. 14:56

request 객체

request 객체 |
 
 
 

=========================================================================

// 클라이언트 정보 및 서버정보 읽기

=========================================================================

getRemoteAddr()              String          웹서버에 연결한 클라이언트의 IP 주소를 가져온다.

getContentLength()          long            클라이언트가 전송한 요청 정보의 길이를 구해온다.

getCharacterEncoding()    String          클라이언트가 요청 정보를 전송할 때 사용한 캐릭터의 인코딩을 구해온다.

getContentType()             String          클라이언트가 요청 정보를 전송할 때 사용한 컨텐츠의 타입을 구해온다.

getProtocol()                     String          클라이언트가 요청한 프로토콜을 구한다.

getMethod()                      String          웹 브라우저가 정보를 전송할 때 사용한 방식을 구한다.

getRequestURI()               String          웹 브라우저가 요청한 URL에서 경로를 구한다.

getContextPath()             String           JSP페이지가 속한 웹 어플리케이션의 콘텍스트 경로를 구한다.

getServerName()              String           연결할 때 사용한 서버 이름을 구한다.

getServerPort()                int                서버가 실행 중인 포트 번호를 구한다.

 

 

===========================================================================

//HTML폼과 요청파라미터 처리

===========================================================================

getParameter(String name)                  String         이름이 name인 파라미터의 값을 구한다 (Request("name") 과 동일)

getParameterValues(String name)        String[]      이름이 name인 모든 파라미터의 값을 배열로 가져온다.

getParameterNames()                           java.util.Enumeration       웹브라우저가 전송한 파라미터의 이름을 구한다.

getParameterMap()                               java.util.Map                  웹브라우저가 전송한 파라미터의 맵을 구한다.

 

ex> name파람 = request.getParameter("name")

      Enumeration enum = request.getParameterNames();

         while(enum.hasMoreElements)

              String name = (String)enum.nextElement();

 

 

========================================================================

//요청 헤더 정보의 처리

========================================================================

getHeader(String name)           String               지정한 이름의 헤더값을 구한다.

getHeasers(String name)          java.util.Enumeration              지정한 이름의 헤더 목록을 구한다.

getHeaderName()                      java.util.Enumeration              모든 헤더의 이름을 구한다.

getIntHeader(String name)        int                   지정한 헤더의 값을 정수값으로 읽어온다.

getDateHeader(String name)     long                지정한 헤더의 값을 시간값으로 읽어온다(1970년1월1일 이후로 흘러간 1/1000초

                                                                           단위로 읽어온다.)

ex> Enumeration enum = request.getHeaderNames();

        while(enum.hasMoreElements()){

            String headerName = (String)enum.nextElement();

            String headerValue = request.getHeader(headerName);

        }

 

 

 

=======================================================================

//값 설정하기(Attribute)

=======================================================================

setAttribute(String name, Object values)        void                                  이름이 name인 속성의 값을 values로 저장한다.

getAttribute(String name)                                Object                              이름이 name인 속성의 값을 구한다.

removeAttribute(String name)                          void                                 이름이 name인 속성을 삭제한다.

getAttributeNames()                                         java.util.Enumeration      속성의 이름 목록을 구한다.

 

## 주의 : setAttribute 에서 값이 Object이기 때문에 int, double과 같은 기본 데이터 타입은 속성값에 할당 할 수 없다. 이유는 Object가 아니기 때문이다. 이 경우엔 레퍼 클래스를 사용해야 한다.

      Integer intValue = new Integer(100);

      request.setAttribute("radio", intValue); 

      ...

      Integer intValue = (Integer)request.getAttribute("radio");

      int value = intValue.intValue();

'My work space > JSP/Servlet' 카테고리의 다른 글

세션설정,세션에서 값 가져오기  (0) 2008.09.08
session.setAttribute 에서 주의할 점  (0) 2008.09.08
request.getAttribute  (0) 2008.09.08
jsp/Servlet 기본2  (0) 2008.09.08
JSP/Servlet 기본  (0) 2008.09.08
2008. 9. 8. 14:55

request.getAttribute

<%@ page import="java.util.Date" %>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<% Date value1=(Date)request.getAttribute("currendDate"); %>
현재 request 기본객체의 "currentDate" 속성 값:<%=value1 %>
<p>
<%
 request.setAttribute("currentDate", new Date());
 value1=(Date)request.getAttribute("currentDate");
%>

값 설정 후, "currentDate" 속성 값 :<%=value1 %>
<p>
<%
 request.removeAttribute("currentDate");
 value1=(Date)request.getAttribute("currentDate");
%>
값 삭제후 "currentDate" 속성 값: <%=value1 %>
</body>
</html>

'My work space > JSP/Servlet' 카테고리의 다른 글

session.setAttribute 에서 주의할 점  (0) 2008.09.08
request 객체  (0) 2008.09.08
jsp/Servlet 기본2  (0) 2008.09.08
JSP/Servlet 기본  (0) 2008.09.08
게시판만들기-검색하기(펌)  (0) 2008.09.08
2008. 9. 8. 14:55

jsp/Servlet 기본2

@ client 에서 HTTP 프로토콜에 따라서 값을 보내는 방식
-두가지 방식이 있다.


1)GET : Request-URI에 붙여서 보내는 방식 : => 파라미터명=값&파라미터명=값
-> get방식의 단점: binary Data 전송불가!!
-> Request_URL를 저장 할때 Data도 동시에 저장할 수 있어서 반복적인 요청이 가능.

GET/study/Calculator?op=plus&a=1&b=12 HTTP/1.1
헤더이름: 값
......
......


2)POST : Message body 에 보내는 방식
-> Binary Data 전송 가능!!
-> 전송하는 Data가 사용자에게 보이지 않는다. 즐겨찾기에 Data 저장은 안됨. 어느정도 보안이 가능

POST/study/Calculator HTTP/1.1
헤더이름 : 값
....
....

op=plus&a=1&b=12


@  URI(Uniform Resource Identifier)  -> 인터넷 상에서 자원을 구분하는 식별자
1) URL(Uniform Resource Locator) 
http://.../.../
2) URN(Uniform Resource Name)     :: ... :: ... ::

 

@ concrete method vs abstract method

- concrete method : 구현된 메소드
예)
public int plus(int a, int b){
 return a+b;
}

- abstract method : 구현되지 않는 메소드
 => 메소드의 구현을 자식 클래스에 맡긴다.
 => 메소드의 동작이 상황에 따라 바뀔수 있을때, 해당 메소드를 abstract 메소드로 만든다.
예)
public abstract int plus(int a, int b);


@HTTPServlet & GenericServlet
-GenericServlet: GET & POST 를 구분하지 못함. Servlet interface의 5개의 메소드중에 4개를 구현함
-HTTPServlet : Service메소드에서 POST방식이냐 GET방식이냐에 따라 doPost , doGet을 호출한다.


@ JSP?
-Servlet 기술에서 출력부분의 프로그래밍을 개선하기 위한 기술.
-출력할 내용은 그냥 작성, 자바코드는 특정 태그안에 작성
-이렇게 작성된 JSP파일은 실행시 Java 소스코드로 변환되고 컴파일 되어서 Servlet으로서 실행된다
.


@ JSP에서 자바코드는 어떻게 작성하나요?

<% 자바코드 %>                        ---> Scriptlet
=> 태그안의 내용이 자바소스코드로 복사된다.

<%! 필드선언 및 메소드 선언%>         ---> Declaration
=> 태그안에 내용이 클래스 선언내에 그대로 복사된다.
_JspService()메소드 안에 들어간다.

<%= 값 %>                             ---> Expression Element
=> 태그안의 내용이 출력문으로 바뀐다.
예)out.wirte(값);

보통 이곳에 저장된다. C:\Sun\AppServer\domains\domain1\generated\jsp\j2ee-modules\StudyWeb\org\apache\jsp


@ JSP Engine vs Servlet Container
"Jsp Engine"
=> .jsp 파일을  .java 자바 서블릿소스 파일로 변환하고, 컴파일 하는 역할.

"Servlet Container"
=> Servlet클래스를 life-cycle을 관리.

 

@Presentation Logic
- UI 출력을 담당하는 프로그램 코드

@ Business Logic
- Data를 가지고 원하는 결과가 나오도록 연산을 수행하는 코드

@ Data Access Logic
- Data 의 Persistance(지속성)를 유지하도록 하는 기술

@ Persistance ?
- 컴퓨터를 on/off 한 후에도 Data를 유지되게 하는것.
-방법
 1) 직접 File System 에 저장한다.(HDD 에 저장)
 2) DBMS를 통해 간접적으로 관리.


< jsp 실습 >

@ Borad 만들기 : Level 1
-Architecture
[JSP] <----> [DBMS]

@ Borad 만들기 : Level 2
-JSP 에서 Business & Data Access Logic 을 분리
 -이점:
 1) Business @ Data Access Logic 을 재사용 가능
 2) 유지 보수가 쉽다.
 -Architecture
[JSP] <---> [Business @ Data Access Logic] <---> [DBMS]

@ Borad 만들기 : Level 3
-Business & Data Access Logic을 각각 분리
-이점
 1) Persistance 층을 분리 함으로써 DBMS의 종속에서 어느정도 벗어난다.
 2) Business 층은 재사용 가능
 -Architecture
[JSP] <---> [Business Logic] <---> [Data Access Logic] <---> [DBMS]

@ Borad 만들기 : Level 4 (EJB Programming)
-"Presentation Layer" 과 "Business & Data Access Layer" 다른 컴퓨터로 분산.
-즉, "Business & Data Access Layer" 를 다른 컴퓨터에 분산시킬수 있도록 준비
 -Architecture
[JSP] <---> [Business Logic: EJB] <---> [ Data Access Logic : Persistance API] <---> [DBMS]
[Java App.]

@ Borad 만들기 : Level 5 (Web Service Programming)
- Business Layer 를 다른 프로그래밍 언어에서 사용할 수 있도록 한다.
 -Architecture
 [JSP] <---> [Business Layer: Web Service] <---> [Data Access Logic: Persistance API] <---> [DBMS]
 [C++ .NET]
 [C# .NET]
 [VB .NET]
 [Java App.]

<Borad 만들기 :Level 1>
@ 테이블 준비 : 데이터를 저장할 틀을 준비
 테이블 명: Borad
 컬럼목록:
no                integer          자동증가     Primary Key 고유번호
caption        varchar(200)   not null         제목
content         text                                  내용
writer          varchar(50)     not null         작성자
password    varchar(20)    not null         암호
count          integer           default(0)     조회수
regdate        date              not null         등록일

 

@ island of Data
- Application 마다 별도로 데이터 관리함으로써 Data 고립되는 문제가 발생
- 즉, application 간 Data가 synchronous 하게 운영하기가 힘들어지는 현상

 

@ DBMS의 탄생배경?
 - 데이터섬(islands of data)으로 동기화 문제 발생.
 - Application 개발시 Persistance를 다루는 부분이 매번 중복됨.
==> Data를 전문적으로 관리해주는 시스템이 필요하게 됨.

 

@ SQL(Structured Query Lanaguage)
- Application 이 DBMS와 소통수단.
- 의사소통수단:
 1) Data Definition: 테이블 생성및 제거,스토어드 프로시저 생성및 제거
 2) Data Manipulation : insert, update, delete
 3) Data Query : Select
 등의 작업 DBMS에 작업 요청할때 사용하는 문법

 

@ JDBC ?
- Java Application 에서 DBMS에 SQL 질의를 전달하고 응답 받을때 사용하는 도구.
- 종류
    --Application DBMS 접근 Architecture--
 1) Type 1(ODBC_JDBC Bridge)
 2) Type 2(native(Vendor) API call)
 3) Type 4(DBMS protocol)


@ ODBC(Open DataBase Connectivity) ?
- 특정 DBMS에 종속되지 않고 DBMS와 통신할 수 있도록 정의된 프로그래밍 도구(function)
- DBMS에 접근할때 사용할 도구에 대해 표준화 시킨것
- 단점: Vendor API 에 비해 속도가 느리다.
- 장점: DBMS에 독립적이다.


@ Vender API(Application Programming Interface)?
- DBMS를 제작한 회사에서 프로그래밍할때 사용하라고 제공해준 도구(function)
- 단점: 특정 DBMS에 종속되는 프로그램을 생산.

'My work space > JSP/Servlet' 카테고리의 다른 글

request 객체  (0) 2008.09.08
request.getAttribute  (0) 2008.09.08
JSP/Servlet 기본  (0) 2008.09.08
게시판만들기-검색하기(펌)  (0) 2008.09.08
게시판만들기-페이지나누기(펌)ASP  (0) 2008.09.08