2011년 6월 13일 월요일

자카르타 프로젝트 HttpClient와 FileUpload 사용하기

August 2004 Discuss this Article
Adapted from:
Pro Jakarta Commons, by Harshad Oak
Publisher: Apress
ISBN: 1590592832
인터넷 상에서 이루워지는 모든 커뮤니케이션은 파일 전송 프로토콜 (FTP), 단순 전자우편 전송 프로토콜 (SMTP), 우체국 통신 규약 (POP), 하이퍼 텍스트 전송 프로토콜 (HTTP) 과 같은 표준 프로토콜을 사용하여 이루어진다.
HTTP은 World Wide Web상에서 가장 필수적이고 가장 대중적인 프로토콜이다. 오늘날 많은 어플리케이션 폭넒게 사용하는 프로토콜이다.
만일 자바어플리케이션이 HTTP을 사용하여 상호 작용한다면 HTTPClient 컴포넌트는 조금더 쉽게 할 수 있는 방식을 제공한다. 이 컴포넌트를 사용한다면 HttpClient컴포넌트에서 제공하는 클래스와 메소드을 이용함으로 프로토콜의 기술적인 측면에서의 걱정을 해소할수 있다. 이 Article에서는 HTTPClient 컴포넌트의 몇가지 사용예를 살펴볼것이다.
우리는 서버측 파일 업로드 업무을 지원하는 FileUpload 컴포넌트에 대하여서도 간단하게 살펴 볼것이다. 그리고 마지막으로 우리는 HTTPClient와 FileUpload컴포넌트을 함께사용한 예를 살펴 볼것이다.
NOTE : 이 Article에서 작성된 모든 예제는 Tomcat 4.0.6이상 버전에서 테스트 되었습니다.
컴포넌트 설치 : http://jakarta.apache.org/commons/index.html에서 위 두가지의 컴포넌트을 다운로드 받을수 있다. 이글을 쓰고 있는 현재 두 컴포넌트이 버전은 다음과 같다. 두 컴포넌트는 내부적으로
commons-logging 컴포넌트을 사용함으로 같이 설치 해줘야 합니다.
  • HTTPClient 3.0 Alpha
  • FileUpload 1.0


Introducing HttpClient
HttpClient은 HTTP상에서 커뮤니케이션을 하는 자바 기반의 어플리케이션 개발을 쉽게 할수 있도록 제공한다. 우리가 웹 브라우저 또는 그에 준하는 어플리케이션을 개발한다면 HttpClient은 우리에게 클라이언트 코드 개발에 도움을 줄수있다.
이름에서 의미하는것과 같이 HttpClient는 오직 HTTP 클라이언트 코드을 위한 컴포넌트이지 HTTP 요청을 처리하는 서버측 프로세스을 지원하지는 않는다.

HttpClient는 다음과 같은 특징을 가지고 있다.
  • HTTP 버전 1.0, 1.1을 구현한다.
  • HTTP 메소드 GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE을 구현한다.
  • HTTPS와 Proxies을 이용한 연결을 지원한다.
  • Basic, Digest, NT 근거리 통신 매니저(NTLM)을 이용한 인증을 지원한다.
  • Cookie 핸들링


Using HttpClient
HttpClient은 Commons Logging 컴포넌트인 commons-logging.jar을 사용한다. 이는 자카르타 아파치 Common프로젝트 사이트에서 다운받을 수 있다.

Using the GET Method
Get메소드는 대부분의 HTTP 요청을 보내는방식이다. 하이퍼 링크 같은 경우는 GET방식의 대표적이라 할수 잇겠다. 여기서 HttpClient의 GET방식 요청 예제를 살펴본다.

이 샘플을 테스트 하기전에 서버측에는 요청에 응답을 할 수 있는 Servlet을 등록해야 한다. 여기서는 userInfo클래스을 userinfo.do라는 명칭으로 매핑시켜 사용한다. 그리고 클라이언트에서 서버측으로 전송되는 파라미터는 , firstname, lastname, email 3가지 이다.

서버측 Servlet
package httpClient;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class userInfo extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=MS949";
public void init(ServletConfig config)
throws ServletException {
super.init(config);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("UserInfo GET Method Call -->");
this.doProcess(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("UserInfo POST Method Call -->");
this.doProcess(request, response);
}
public void doProcess(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
java.util.Enumeration e= request.getHeaderNames();
while (e.hasMoreElements()) {
String headerName=(String)e.nextElement();
System.out.println(headerName +" = "+request.getHeader(headerName));
}
ServletInputStream ins = request.getInputStream();
ByteArrayOutputStream outs =
new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int read = 0;
while ((read = ins.read(buffer, 0, 1024)) != -1) {
outs.write(buffer, 0, read);
}
System.out.println(outs.toString());
out.println("<html>");
out.println("<head><title>userInfo</title></head>");
out.println("<body>");
out.println("<p>The servlet has received.</p>");
Enumeration names = request.getParameterNames();
String name = "";
while(names.hasMoreElements()) {
name = names.nextElement().toString();
System.out.println(name +" : "+request.getParameter(name));
out.println("<p>"+name +" : "+request.getParameter(name)+"</p>");
}
out.println("</body></html>");
out.close();
}
}


Web.xml에 Servlet등록
<servlet>
<servlet-name>userInfo</servlet-name>
<servlet-class>httpClient.userInfo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>userInfo</servlet-name>
<url-pattern>/userinfo.do</url-pattern>
</servlet-mapping>


HttpClient 코드
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
public class SubmitHttpForm {
private static String url =
"http://15.32.37.194:8988/HttpClient/userinfo.do";
public static void main(String[] args) {
//Instantiate an HttpClient
HttpClient client = new HttpClient();
//Instantiate a GET HTTP method
HttpMethod method = new GetMethod(url);
//Define name-value pairs to set into the QueryString
NameValuePair nvp1= new NameValuePair("firstName","fname");
NameValuePair nvp2= new NameValuePair("lastName","lname");
NameValuePair nvp3= new NameValuePair("email","email@email.com");
method.setQueryString(new NameValuePair[]{nvp1,nvp2, nvp3});
try{
int statusCode = client.executeMethod(method);
System.out.println("QueryString>>> "+method.getQueryString());
System.out.println("Status Text>>>"
+HttpStatus.getStatusText(statusCode));
//Get data as a String
System.out.println(method.getResponseBodyAsString());
//OR as a byte array
byte [] res = method.getResponseBody();
//write to file
FileOutputStream fos= new FileOutputStream("donepage.html");
fos.write(res);
//release connection
method.releaseConnection();
}
catch(IOException e) {
e.printStackTrace();
}
}
}


서버측 로그
UserInfo GET Method Call -->
USER-AGENT = Jakarta Commons-HttpClient/2.0.1
HOST = 15.32.37.194:8988
email : email@email.com
lastName : lname
firstName : fname


위 예제는 서버측으로 클라이언트 요청을 보내고 요청에 대한 응답을 받아서 “donepage.html”이라는 파일에 응답내용을 저장하는 클라이언트입니다.

org.apache.commons.httpclient.HttpStatus 클래스에는 요청에 대한 응답코드에 대한상태가정의 되어있습니다.
우리는 GET메소드을 사용하여 Name/Value쌍의 파라미터를 전송하는 방식을 간단하에 살펴 보왔다.

Using the POST Method
이번 예제에서는 XML 문서을 HTTP POST 메소드로 서버측에 보내는 예제를 살펴볼것이다.
전송될 XML문서 post.xml
<?xml version='1.0' encoding='KSC5601'?>
<PERSONS>
<PERSON>
<FIRSTNAME>Yun Chang</FIRSTNAME>
<LASTNAME>LEE</LASTNAME>
<EMAIL>craftlee@nate.com</EMAIL>
</PERSON>
</PERSONS>


Post 전송 HttpClient 코드
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
public class PostAFile {
private static String url =
"http://15.32.37.194:8988/HttpClient/userinfo.do";
public static void main(String[] args) throws IOException {
HttpClient client = new HttpClient();
PostMethod postMethod = new PostMethod(url);
client.setConnectionTimeout(8000);
// Send any XML file as the body of the POST request
File f = new File("post.xml");
System.out.println("File Length = " + f.length());
postMethod.setRequestBody(new FileInputStream(f));
postMethod.setRequestHeader("Content-type",
"text/xml; charset=KSC5601");
int statusCode1 = client.executeMethod(postMethod);
System.out.println("statusLine>>>" + postMethod.getStatusLine());
postMethod.releaseConnection();
}
}


서버측 로그
UserInfo POST Method Call -->
CONTENT-TYPE = text/xml; charset=KSC5601
USER-AGENT = Jakarta Commons-HttpClient/2.0.1
HOST = 15.32.37.194:8988
CONTENT-LENGTH = 195
<?xml version='1.0' encoding='KSC5601'?>
<PERSONS>
<PERSON>
<FIRSTNAME>Yun Chang</FIRSTNAME>
<LASTNAME>LEE</LASTNAME>
<EMAIL>craftlee@nate.com</EMAIL>
</PERSON>
</PERSONS>


이 방식은 파일 첨부방식을 나타내는 것이기도 하다. 우리가 쓰고있는 FileUpLoad 컴포넌트도 이와 같은 방식을 사용하고 있다.

Managing Cookies
Cookie관리 예제를 살펴본다.
서버측 JSP
<%@ page contentType="text/html;charset=MS949"%>
<%
Cookie[] cookies= request.getCookies();
for (int i = 0; i < cookies.length; i++) {
System.out.println(cookies[i].getName() +" = "+cookies[i].getValue());
}
//Add a new cookie
response.addCookie(new Cookie("XYZ","12345"));
%>


HttpClient 코드
package httpClient;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
public class CookiesTrial {
private static String url =
"http://15.32.37.194:8988/HttpClient/cookieServer.jsp";
public static void main(String[] args) throws Exception {
//A new cookie for the domain 127.0.0.1
//Cookie Name= ABCD Value=00000 Path=/ MaxAge=-1 Secure=False
Cookie mycookie = new Cookie("15.32.37.194", "ABCD", "00000", "/", -1, false);
//Create a new HttpState container
HttpState initialState = new HttpState();
initialState.addCookie(mycookie);
//Set to COMPATIBILITY for it to work in as many cases as possible
initialState.setCookiePolicy(CookiePolicy.COMPATIBILITY);
//create new client
HttpClient httpclient = new HttpClient();
//set the HttpState for the client
httpclient.setState(initialState);
GetMethod getMethod = new GetMethod(url);
//Execute a GET method
int result = httpclient.executeMethod(getMethod);
System.out.println("statusLine>>>"+getMethod.getStatusLine());
//Get cookies stored in the HttpState for this instance of HttpClient
Cookie[] cookies = httpclient.getState().getCookies();
for (int i = 0; i < cookies.length; i++) {
System.out.println("nCookieName="+cookies[i].getName());
System.out.println("Value="+cookies[i].getValue());
System.out.println("Domain="+cookies[i].getDomain());
}
getMethod.releaseConnection();
}
}


결과
statusLine>>>HTTP/1.1 200 OK
CookieName=ABCD
Value=00000
Domain=15.32.37.194
CookieName=XYZ
Value=12345
Domain=15.32.37.194
CookieName=JSESSIONID
Value=ac3f1396ad9b4a2b8f8e939eb75c843d
Domain=15.32.37.194
Process exited with exit code 0.


CAUTION HttpClient 코드는 org.apache.commons.httpclient.Cookie클래스을 이용하고,JSP과servlet코드는 javax.servlet.http.Cookie 클래스을 이용한다.

HTTPS and Proxy Servers
HttpClient는 HTTPS 프로토콜도 통상의 URLs인식하고 구동된다. HTTPS 프로토콜은 Secure Soocket Extension(JSSE) 시스템에 설치 되어있어야 하며 JSSE는 JSDK1.4 버전이상에서는 포함되어있으며 이하버전에서는 별로의 설치해야한다.
만일 porxy서버을 통한 접속일 경우 다음과 같이 PROXYHOST, Port을 넣어주면된다.
HttpClient client = new HttpClient();
HostConfiguration hConf= client.getHostConfiguration();
hConf.setProxy("PROXYHOST ", 9999);


Introducing FileUpload
FileUpload 컴포넌트는 서버측에 파일 첨부을 쉽게 해줍니다. FileUpload 컴포넌트는 클라이언트 단이 아닌 서버측에서사용된다는것에 주의 해야합니다. 파일 첨부의 시작은 HTML을 이용하며 서버측에서는 FileUpload 컴포넌트을 사용합으로 쉽게 처리하고, 적당한 위치에 저장할수 있습니다.

Using HTML File Upload
다들 아시는 부분이라 이부분의 설명은 제외하고 예제 소스를 바로 살펴봅니다.
fileUP.html
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"/>
<TITLE>File Upload Page</TITLE>
</HEAD>
<BODY>Upload Files
<FORM name="filesForm" action="ProcessFileUpload.jsp"
method="post" enctype="multipart/form-data">
File 1:<input type="file" name="file1"/><br/>
File 2:<input type="file" name="file2"/><br/>
File 3:<input type="file" name="file3"/><br/>
<input type="submit" name="Submit" value="Upload Files"/>
</FORM>
</BODY>
</HTML>


파일 업로드의 시작점은 HTML은 Form의 속성이 method="post" enctype="multipart/form-data" 이어야 합니다. FileUpload 컴포넌트는 enctype에 의해서 전송되는 파라미터를 inputStream으로 받을지 Reader로 받을지 결정합니다.

서버측 프로그램 ProcessFileUpload.jsp
<%@ page contentType="text/html;charset=windows-1252"%>
<%@ page import="org.apache.commons.fileupload.DiskFileUpload"%>
<%@ page import="org.apache.commons.fileupload.FileItem"%>
<%@ page import="java.util.List"%>
<%@ page import="java.util.Iterator"%>
<%@ page import="java.io.File"%>
html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Process File Upload</title>
</head>
<%
System.out.println("Content Type ="+request.getContentType());
DiskFileUpload fu = new DiskFileUpload();
// If file size exceeds, a FileUploadException will be thrown
fu.setSizeMax(1000000);
List fileItems = fu.parseRequest(request);
Iterator itr = fileItems.iterator();
while(itr.hasNext()) {
FileItem fi = (FileItem)itr.next();
//Check if not form field so as to only handle the file inputs
//else condition handles the submit button input
if(!fi.isFormField()) {
System.out.println("nNAME: "+fi.getName());
System.out.println("SIZE: "+fi.getSize());
//System.out.println(fi.getOutputStream().toString());
File fNew= new File(application.getRealPath("/"), fi.getName());
System.out.println(fNew.getAbsolutePath());
fi.write(fNew);
}
else {
System.out.println("Field ="+fi.getFieldName());
}
}
%>
<body>
Upload Successful!!
</body>
</html>


Using HttpClient-Based FileUpload
위 단에서 HTML의 역할을 HttpClient을 이용하여 작성하여본다.
JSP파일의 내용은 변함이 없고 클라이언트 코드을 변경함으로써 가능하다.
HttpClient 컴포넌트는 multipart-encoded을 지원하기 위해 다음과 같은 클래스를 제공합니다. org.apache.commons.httpclient.methods.MultipartPostMethod 이 클래스을 이용하여 예제를 작성해 봅니다.
HttpClient 코드
package httpClient;
import java.io.File;
import java.io.IOException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.MultipartPostMethod;
public class HttpMultiPartFileUpload {
private static String url =
"http://15.32.37.194:8988/HttpClient/ProcessFileUpload.jsp";
public static void main(String[] args) throws IOException {
HttpClient client = new HttpClient();
MultipartPostMethod mPost = new MultipartPostMethod(url);
client.setConnectionTimeout(8000);
// Send any XML file as the body of the POST request
File f1 = new File("students.xml");
File f2 = new File("academy.xml");
File f3 = new File("academyRules.xml");
System.out.println("File1 Length = " + f1.length());
System.out.println("File2 Length = " + f2.length());
System.out.println("File3 Length = " + f3.length());
mPost.addParameter(f1.getName(), f1);
mPost.addParameter(f2.getName(), f2);
mPost.addParameter(f3.getName(), f3);
int statusCode1 = client.executeMethod(mPost);
System.out.println("statusLine>>>" + mPost.getStatusLine());
mPost.releaseConnection();
}
}

댓글 없음:

댓글 쓰기

ETL 솔루션 환경

ETL 솔루션 환경 하둡은 대용량 데이터를 값싸고 빠르게 분석할 수 있는 길을 만들어줬다. 통계분석 엔진인 “R”역시 하둡 못지 않게 관심을 받고 있다. 빅데이터 역시 데이터라는 점을 볼때 분산처리와 분석 그 이전에 데이터 품질 등 데이...