Apache Commons Fileupload의 Stream API 이용시 폼 정보 얻기.
2010-07-30 09:38:30

맨처음에 Form의 정보중 파일이 넘어오는 것을

FileItemIterator의 하나의 FileItemStream을 가지고 읽으면서

폼정보 인지 아닌지만 파악했었다.

하지만 이는 지극히 예제 소스에 의존한 것으로 폼에서 같이 오는 텍스트 정보를 얻을수

없었다.

html 에 대한 이해도가 없던 나는 파일과 텍스트를 함께 보내는 것은 불가능 한것인가하고

생각하다가 여러 사이트에서 당연스레 가능하다는 것을 알았고 말도 안된 다는 것을 알았다.

사이트에보면 단순 Apache commons fileupload에서 폼정보를 얻어오는 것은 나온다.

단순하게 FileItem의 getString() 메소드를 쓰면 되는 것이다.

하지만 Stream을 이용하여 속도가 빠르고 용량도 특별히 지정하지 않아도 잘 되고

Windows7보다 속도는 느리더라도 그냥 API보다는 확실히 빠른 기능을 이용하고 싶다면

이방법은 안된다. 왜냐면 FileItemStream을 이용하기 때문!!

서론이 길었지만

쉽다;

getFieldName로 필드 이름(html의 name 속성)을 알아내고

그냥 스트림을 openStream()으로 읽어서 버퍼에 담고

그 byte버퍼를 Sting에 유니코드로 넣으면 되는것이다.

if (item.getFieldName().equals("upfile")) { //파일 내용 파일에 쓰기

if(printed){

writeFile=new File(path+FilenameUtils.getName(item.getName()));

outFile=new FileOutputStream(writeFile);

printed=false;

}

byte buf[]=new byte[1024];

try{

int len;

while((len=stream.read(buf))>0){

outFile.write(buf,0,len);

}

outFile.close();

stream.close();

}catch(Exception e){

out.print("에러가 발생했어요.. "+e.toString());

}

}else if(item.getFieldName().equals("note")){ //폼 데이터 얻어오기

byte[] buf=new byte[1024];

stream.read(buf);

String note = new String(buf,"utf-8");

out.print("보낸글 : "+note);

stream.close();

}

보라; 간결하지 않은가 ㅋ

이 쉬운걸 왜 나는 3시간이나 찾아 헤매었단 말인가!!

막히면 해당 정보 조금 더 공부하고

Javadoc을 잘 읽고 메소드를 확인하는

올바른 방법을 택했더라면 좀더 빨리 해결 했을 것이다.

불가능도 없고 막연한 두려움도 필요없다.

▼ more
폼의 송신
2010-07-30 08:57:03

이 항목들 사용도구 폼 데이터의 처리 대리자(agent)에게 송신 방법을 설명한다.

17.13.1 폼의 송신(submit) 방법

FORM 엘레멘트의 method(방법) 애트리뷰트는 폼(form)을 처리 대리자에게 보내는데 사용되는 HTTP 방법(method)을 지정한다. 이 애트리뷰트는 다음 두가지 값을 가질 수 있다.

get: HTTP의 "get" 방법으로, 폼 데이터 세트(form data set)가 action 애트리뷰트에 지정 된 URI에 해 물음표 ("?")로 분리하여 추가되고, 이 새 URI는 처리(processing) 대리자(agent)에게 보내진다.

post: HTTP의 "post" 방법으로, 폼 데이터 세트는 폼의 본체에 포함되어 처리 대리자에게 보내진다.

"get" 방법은 폼이 다른 효과(side-effects)를 유발시키지 않을 때에 사용하여야 한다. 많은 데이터베이스(database) 검색들은 보이는 다른 효과(side-effect)가 없이 이상적인 "get" 방법이 적용된다.

예를 들어, 만일 폼이 데이터베이스를 수정하거나, 서비스에 등록(subscription)하는 등, 서비스가 다른 효과를 유발하는 폼의 처리를 한다면, "post" 방법이 사용되어야 한다.

주석: "get" 방법은 폼 데이터 세트의 값을 ASCII 글자로 제한한다. enctype="multipart/form-data"와 함께 사용하는 "post" 방법 만이 전체 [ISO10646] 글자 세트를 커버하도록 지정되었다.

17.13.2 성공적 제어

성공적 제어(successful control)는 유효한 송신(submit)이다. 모든 성공적 제어는 송신되는 폼 데이터 세트(form data set)의 부분으로 그 제어 이름과 그 현재값의 짝을 갖는다. 성공적 제어는 FORM 엘레멘트 안에서 정의되고 제어 이름을 가져야한다.

그러나:

불활성(disabled) 제어은 성공적이 될 수 없다.

만일 폼이 한개 이상의 송신 단추들를 갖는다면, 활성화 된 송신 단추 만이 성공적이다.

모두 "on" 된 체크박스(checkboxe)는 성공적이 될 수 있다.

name애트리뷰트에 같은 값을 갖는 레디오 단추(radio button)들에서, "on" 된 레디오 단추 만이 성공적이 될 수 있다.

메뉴에서, 제어 이름은 SELECT 엘레멘트에 의하여 제공되고, 그 값은 OPTION 엘레멘트에 의하여 제공된다. 선택 된(selected) 선택 사항 만이 성공적이 될 수 있다.

화일 선택(file select)의 현재값은 하나 혹은 그 이상의 화일 이릅들의 목록이다. 폼의 송신과 동시에, 각 화일의 그 내용은 나머지 다른 폼 데이터와 함께 발송된다. 그 화일 내용은 폼의 컨텐트 타입(content type)에 따라 포장된다.

오브젝트 제어의 현재값은 오브젝트의 적용에 따라 결정된다.

만일 폼이 송신되는데 제어가 현재값을 가지고 있지 않으면, 사용도구는 성공적 제어로 처리하지 말아야한다.

또 한 사용도구는 다음과 같은 경우에 성공적 제어로 간주하지 말아야한다.

재설정 단추(reset button).

declare 애트리뷰트가 설정 된 OBJECT 엘레멘트.

감춰진 제어(hidden control)와 스타일쉬트(style sheet) 설정 때문에 표현되지 않은 제어는 성공적이 될 수 있다. 예를 들어:

이는 값이 이름 "invisible-password"와 짝이되어 폼과 함께 송신(submit)된다.

17.13.3 폼 데이터의 처리

송신 단추(submit button)를 활성화 하는 등으로 사용자가 폼을 송신하면, 사용도구는 다음과 같이 처리한다.

일단계: 성공적 제어(successful control)를 인식한다.

이단계: 폼 데이터 세트를 만듬

폼 데이터 세트(form data set)는 성공적 제어로 부터 제어 이름(control-name)과 현재값(current-value) 짝들로 구성 된 일련의 데이터이다.

삼단계: 폼 데이터 세트를 엔코딩

폼 데이터 세트는 FORM 엘레멘트의 enctype 애트리뷰트에서 지정 된 컨텐트 타입(content type)에 의하여 엔코딩된다.

사단계: 엔코딩 된 폼 데이터 세트의 송신

최종적으로, 엔코딩 된 데이터는 action 애트리뷰트로 지정 된 처리 대리자(processing agent)에게 method 애트리뷰트에 의하여 지정 된 프로토콜(protocol)를 사용하여 보내진다.

이 규격은 폼에 사용 될 수 있는 모든 유효한 송신 방법들이나 컨텐트 타입들을 규정하지 않았다. 그러나, HTML 4 사용도구는 다음 경우들의 처리 방법을 지원하여야 한다.

만일 method가 "get"이고 action은 HTTP URI이면, 사용도구는 action의 값을 갖고, 여기에 `?'를 추가 한 후, 폼 데이터 세트(form data set)를 추가하여야 하여, 컨텐트 타입(content type) "application/x-www-form-urlencoded"을 사용하여 엔코딩하여야 한다. 그후 사용도구은 이 URI에 연결을 한다. 이 시나리오(scenario)에서, 폼 데이터는 ASCII 코드로 국한한다.

만일 method가 "post"이고 action이 HTTP URI이면, 사용도구는 action 애트리뷰트의 값과, enctype 애트리뷰트에 의하여 지정 된 컨텐트 타입에 의해 만들어 진 메세지에 따라 HTTP "post" 송신을 수행한다.

action 또는 method의 다른 값에서는, 작동이 지정되어 있지 않았다.

사용도구는 HTTP "get"과 "post" 이전(transaction)의 송신을 표현하여야 한다.

17.13.4 폼의 컨텐트 타입(content type)

FORM 엘레멘트의 enctype 애트리뷰트는 서버에 송신을 위하며 폼 데이터 세트(form data set)의 엔코드에 사용 된 컨텐트 타입(content type)을 지정한다. 사용도구는 아래 목록의 컨텐트 타입을 지원하여야 한다. 다른 컨텐트 타입들의 작동이 지정되어 있지 않다.

URI 애트리뷰트 값에서 앰퍼샌드("&") 에스케이핑(escaping)도 참고하라.

컨텐트 타입 "application/x-www-form-urlencoded"

이는 컨텐트 타입(content type)의 디폴트 값이다. 이 컨텐트 타입으로 송신되는 폼은 다음과 같이 엔코딩되어야 한다.

제어 이름(Control name)들과 값들이 아스키 값으로(escaped(된다. 공간 글자들은 `+'으로 대체되고, 그 후 [RFC1738] 항목 2.2에 설명 된 바와 같이 예약(reserved) 글자들이 아스키 값으로(escaped) 된다. 비 알파벳(Non-alpha) 글자들은 퍼센트 기호와 해당 글자의 ASCII 코드에 해당하는 두개의 16진수로 된 `%HH'로 된다. 줄바꿈(line break)은 "CR LF"('%0D%0A')로 된다.

제어 이름과 값은 문서에 나타나는 순서에 따라 목록화된다. 이름은 그 값과 `='로 분리되고, 제어 이름과 값의 짝은 서로 `&'로 분리된다.

컨텐트 타입 "multipart/form-data"

주석: 과거 버전 부합성 문제, "multipart/form-data"와 기타 컨텐트 타입(content type)들과의 관계, 성능 문제 등을 포함하여, 화일 업로드(upload)에 대 한 추가적인 정보는 [RFC2388]을 참조하라.

부록의 폼의 보안 문제를 참조하라.

컨텐트 타입 "application/x-www-form-urlencoded"는 많은 양의 이진수(binary) 데이터 또는 비아스키(non-ASCII) 글자를 포함하는 텍스트에서는 효과적이 아니다. 화일, 비아스키 데이터, 이진수 데이터을 포함하는 폼의 송신(submit)에는 컨텐트 타입(content type) "multipart/form-data"가 사용되어야 한다.

이진(binary) "multipart/form-data"는 [RFC2045]에 소개 된 모든 복수 MIME 데이터 흐름의 규칙을 따른다. "multipart/form-data" 정의는 [IANA] 리지스트리(registry)에 있다.

"multipart/form-data" 메세지는 성공적 제어 부분들의 연속을 포함하여 나타낸다. 각 부분들은 문서에 나타나는 제어와 상응하는 같은 순서에따라, 처리 대리자(processing agent)에게 보내 진다. 부분의 구획은 어떤 데이터에도 나타나지 않아야 하며, 그 방법은 이 규격의 법위 밖이다.

모든 복수 MIME 타입들과 같이, 각 부분은 디폴트가 "text/plain"인 선택적 "Content-Type" 헤더(header)를 갖는다. 사용도구는 "charset" 파라메터(parameter)에 의하여 이루어지는 "Content-Type" 헤더를 제공하여야 한다.

각 부분은 다음을 포함 할 것이다.

값이 "form-data" 인 "Content-Disposition" 헤더.

해당 제어의 제어 이름을 지정하는 name 애트리뷰트. 원래 비아스티(non-ASCII) 글자 세트로 엔코드 된 제어 이름은 [RFC2045]에 소개 된 방법에 따른다.

그래서, 제어 이름 "mycontrol" 인 예제에서, 해당 부분이 지정되었다.

Content-Disposition: form-data; name="mycontrol"

모든 MIME 송신에서와 같이, "CR LF"(`%0D%0A')가 데이터의 열(line)을 구별하기 위하여 사용된다.

각 부분은 엔코드 될 수 있고, 만일 그 부분의 값이 디폴트 엔코딩 (7BIT)과 일치하지 않으면[RFC2045 항목 6 참조], "Content-Transfer-Encoding" 헤더(header)가 제공되어야 한다.

만일 그 화일 내용들이 폼과 함께 송신되면, 그 화일 입력은 적정한 컨텐트 타입으로 지정되어야한다(예를 들어, "application/octet-stream"). 만일 단일 폼 엔트리의 결과로 복수(multiple) 화일들이 돌아온다면, 그 것들은 "multipart/form-data" 안에 깔려 있는(embedded) "multipart/mixed"로 돌아와야한다.

사용도구는 각 송신(submit) 화일의 화일 이름 제공을 시도하여야 한다. 그 화일 이름은 'Content-Disposition: form-data' 헤더의 "filename" 파라메터로, 또는, 복수(multiple) 화일의 경우, 부분의 'Content-Disposition: file' 헤더 안의 "filename" 파라메터로 지정 될 수 있다. 만일 사용자의 운영 체계에서 그 화일 이름이 US-ASCII가 아니면, 그 화일 이름은 대략적으로 되거나 또는 [RFC2045]의 방법을 사용하여 엔코드가 될 수 있다. 이것은, 예를 들어, 업로드 된 화일이 서로 참조(예를 들어, TeX 화일과 그의 ".sty" 보조 스타일 기재)를 포함 할 경우에 편리하다.

예제는 "multipart/form-data" 엔코딩을 설명한다. 다음의 폼을 가정하자.

성명은?
보낼 화일은?

만일 사용자가 "Larry"를 텍스트 입력하고 "file1.txt" 화일을 선택하면, 사용도구는 다음 데이터를 되돌려 보낼 것이다.

Content-Type: multipart/form-data; boundary=AaB03x --AaB03x Content-Disposition: form-data; name="submit-name" Larry --AaB03x Content-Disposition: form-data; name="files"; filename="file1.txt" Content-Type: text/plain ... file1.txt의 내용 ... --AaB03x--

만일 사용자가 두번째 이미지 화일 "file2.gif"을 선택하였다면, 사용도구는 다음과 같은 부분들을 형성 할 것이다.

Content-Type: multipart/form-data; boundary=AaB03x --AaB03x Content-Disposition: form-data; name="submit-name" Larry --AaB03x Content-Disposition: form-data; name="files" Content-Type: multipart/mixed; boundary=BbC04y --BbC04y Content-Disposition: attachment; filename="file1.txt" Content-Type: text/plain ... file1.txt의 내용 ... --BbC04y Content-Disposition: attachment; filename="file2.gif" Content-Type: image/gif Content-Transfer-Encoding: binary ... file2.gif의 내용 ... --BbC04y-- --AaB03x--

[출처] http multipart/form-data 정의|작성자 코베이

▼ more
해야할 것.
2010-07-29 17:19:45

1. 기존의 스캐너 종이를 서버로 올린다.

2. 서버에서 벡터화를 한다.

3. 벡터 정보를 클라이언트로 보낸다.

▼ more
해야할 것.
2010-07-29 17:18:58

1. Mysql에 단문 넣기

2. Source targe으로 DB만들어서 following 정보 입력

▼ more