IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  웹 개발 | XML  >

DWR을 사용하여 Ajax 기반 파일 업로드 포틀릿 개발하기 (한글)

파일 업로드 프로세스 동안 진행 바 디스플레이 하기

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

토론

샘플 코드

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

Xiaobo Yang, Software Developer, STFC e-Science Centre, UK
Robert Allan, Group Leader, STFC e-Science Centre, UK

2007 년 10 월 16 일

파일 업로드는 오늘날 웹 포털의 기본 기능입니다. 이 글에서, Xiaobo Yang과 Rob Allan은 DWR(Direct Web Remoting)을 사용하여 Ajax 기반 파일 업로드 JSR 168-순응 포틀릿을 개발하는 방법을 설명합니다. DWR은 서버 측에 전개된 자바 클래스들을 기반으로 하는 JavaScript를 동적으로 생성할 수 있는 이상적인 Ajax 프레임웍입니다. DWR을 사용하여 포털 서버에서 파일 업로드 진행 상황을 검색하는 방법을 배워봅시다.

머리말

웹 포털은 다양한 리소스와 서비스에 액세스 할 수 있는 중앙 게이트웨이이다. 동시에, 다른 사용자들과 공유되는 리소스를 기여할 수 있는 플랫폼도 제공한다. 사용자들은 사진부터 오디오/비디오 파일, 연구용 데이터에 이르기까지 모든 것을 공유할 수 있다. 따라서, 파일 업로드는 기본적이고도 필수적인 웹 포털 기능이라고 할 수 있다.

오늘날의 웹 포털은 자바 포틀릿 기술에 크게 의존하고 있다. 파일 업로드용 진행 바에 대해서는 Ajax를 사용하는 다양한 개발자들에게 설명했지만, 포틀릿 기반은 아직 발견하지 못했다. 이 글에서는 파일 업로드 프로세스 동안 진행 바를 디스플레이 하는 Ajax 기반 파일 업로드 포틀릿을 개발하는 방법을 설명하겠다. 이 포틀릿은 큰 오디오, 비디오, 과학 파일들을 공유해야 하는 사람들에게 특히 유용하다.

이 글을 이해하려면, Java Servlet과 JavaServer Page (JSP) 사용법에 익숙해야 한다. 또한, 포털과 포틀릿 기술 개발을 이해하는 것이 중요하다. 하지만, 포틀릿 기술에 익숙하지 않더라도, 포기하지 말라. 이 글에서 포틀릿 기술과 유용한 리소스를 소개하겠다.

developerWorks Ajax 리소스 센터
Ajax 리소스 센터는 Ajax 프로그래밍 모델 관련 튜토리얼, 디스커션 포럼, 블로그, wiki, 이벤트, 뉴스 등을 제공하고 있습니다. Ajax에 관한 모든 것이 집대성 되어 있습니다.

이 글에 설명된 파일 업로드 포틀릿을 테스트하기 전에 IBM® WebSphere® Portal Server, Apache Pluto, eXo platform, Liferay Portal 같은 JSR 168 순응 포털 프레임웍들 중 하나를 사용하여 시험할 것이다. 우리가 사용했던 것은 Apache Pluto 1.0.1, JDK 5.0 Update 10, Apache Ant Version 1.6.5이다.

포틀릿의 기본 개념

일반적으로, 포틀릿은 웹 컴포넌트로서 취급될 수 있다. 포틀릿은 서블릿과 비슷하지만, 이것의 초점은 애플리케이션의 표현 레이어(presentation layer)이다. 포틀릿의 전형적인 아웃풋은 웹 포털에 의해 조립될 수 있는 HTML 조각이다.

  • 다중 모델: 하나의 포틀릿은 다른 모드 하에서 다른 뷰들을 가질 수 있다. 예를 들어, 뷰(view) 모드 외에도, 포틀릿은 편집(edit) 모드를 지원하여 사용자들이 각자의 프레퍼런스를 설정할 수 있도록 한다.
  • 다중 윈도우 상태: 포틀릿은 최소화, 최대화 될 수 있다.
  • 커스터마이징 가능한 매개변수: 포틀릿은 매개변수를 정의할 수 있는데, 이는 사용자들에 의해 커스터마이징 될 수 있다.

포틀릿에 대한 자세한 내용은 Java Portlet Specification 1.0, JSR 168을 참조하라. (JSR 168의 후속인 JSR 286은 2007년 후반에 릴리스 될 예정이며, 포틀릿 간 통신과 포틀릿 필터가 강화될 예정이다.) 이 자료의 참고자료 링크.

파일 업로드 포틀릿 시작하기

파일 업로드 포틀릿의 중심은 Apache Commons FileUpload 패키지이다. (이 글에서는 FileUpload라고 칭하겠다.) 서블릿에서 파일 업로드 지원을 비롯하여, Apache Commons FileUpload Version 1.1 패키지는 포틀릿에서도 파일 업로드를 지원한다. 이 글에서는 Apache Commons FileUpload Version 1.2를 사용한다.

기본적으로, 파일 업로드 진행 바를 개발하는데 두 단계가 필요하다.

  1. 파일 업로드 진행에 대해 서버 측에서 검색하기
  2. 포털 서버에서 업로드 진행을 클라이언트 측에서 검색하고 디스플레이 하기

파일 업로드 진행에 대해 서버 측에서 검색하기

FileUpload 패키지는 리스너를 사용하여 파일 업로드 진행을 검색하도록 한다. 파일 업로드 포틀릿의 doUpload() 메소드(다운로드 섹션의 소스 파일에는 uk.ac.dl.esc.gtg.myportlets.fileupload.FileUploadPortlet이라는 이름을 사용함)에서, Listing 1처럼, setProgressListener() 메소드를 호출함으로써 PortletFileUpload용 진행 리스너를 설정했다.


Listing 1. 파일 업로드 패키지용 진행 리스너 설정하기
                
DiskFileItemFactory factory = new DiskFileItemFactory();
PortletFileUpload pfu = new PortletFileUpload(factory);
pfu.setSizeMax(uploadMaxSize); // Maximum upload size
pfu.setProgressListener(new FileUploadProgressListener());
            

FileUploadProgressListener (Listing 2)는 org.apache.commons.fileupload.ProgressListener 인터페이스를 구현하는 리스너이다. update() 메소드는 FileUpload 패키지에 의해 자동으로 호출되어 많은 바이트들이 전송된 방법에 대한 최신 정보를 리프레시한다. 이 글의 구현에서, 진행은 10KB 데이터가 전송될 때 업데이트 된다. 이것은 진행 업데이트가 너무 자주 발생하지 않도록 한다. getFileUploadStatus() 메소드는 현재 파일 업로드 진행을 계산하는데 사용되는데, 이는 DWR을 사용하는 클라이언트에 의해 호출된다. (다음 섹션 참조)


Listing 2. 파일 업로드 진행을 검색하는 파일 업로드 리스너
                
package uk.ac.dl.esc.gtg.myportlets.fileupload;

import java.text.NumberFormat;

import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class FileUploadProgressListener implements ProgressListener {
	private static Log log = LogFactory.getLog(FileUploadProgressListener.class);

	private static long bytesTransferred = 0;

	private static long fileSize = -100;

	private long tenKBRead = -1;

	public FileUploadProgressListener() {
	}

	public String getFileUploadStatus() {
		// per looks like 0% - 100%, remove % before submission
		String per = NumberFormat.getPercentInstance().format(
				(double) bytesTransferred / (double) fileSize);
		return per.substring(0, per.length() - 1);
	}

	public void update(long bytesRead, long contentLength, int items) {
		// update bytesTransferred and fileSize (if required) every 10 KB is
		// read
		long tenKB = bytesRead / 10240;
		if (tenKBRead == tenKB)
			return;
		tenKBRead = tenKB;

		bytesTransferred = bytesRead;
		if (fileSize != contentLength)
			fileSize = contentLength;
	}

}
      

파일 업로드 진행에 대한 클라이언트 측 검색

파일 업로드 진행 시 서버와 클라이언트 간 통신은 Ajax를 사용하여 실현된다. 우리는 Direct Web Remoting (DWR)을 통해 포틀릿에 Ajax 지원을 제공했다. DWR은 Ajax를 웹 개발 프로세스로 가져오는데 이상적인 프레임웍이다. 브라우저의 JavaScript가 서버 측 자바 객체들과 인터랙팅 할 수 있도록 하기 때문이다. 우리 포틀릿에 DWR을 사용하려면, 다음 단계가 필요하다. (DWR 설정 방법에 대한 자세한 정보는 참고자료를 참조하라.)

Direct Web Remoting의 강점은 바로 이것이다. 클라이언트가 서버 측 자바 객체와 통신하고 있다.
  • WEB-INF/web.xml 을 통해 DwrServlet을 설정한다. (Listing 3).
  • WEB-INF/dwr.xml에 한 개 이상의 서버 측 객체를 정의하여 클라이언트가 통신할 수 있도록 한다. Listing 4에서, DWR을 위해 FileUploadProgressListener가 정의되어, 클라이언트는 자동 생성된 JavaScript를 호출할 수 있다. 또한, getFileUploadStatus 메소드만이 클라이언트에 의해 호출될 수 있도록 한다. 다른 퍼블릭 메소드인 update는 액세스 될 수 없다. (Listing 2).
  • fileupload-view.jsp에 DWR 관련 JavaScript 코드를 포함시킨다. (Listing 5).
  • 포틀릿 애플리케이션에 DWR 라이브러리를 포함시킨다.

Listing 3. WEB-INF/web.xml에서의 DwrServlet 설정
                
<!-- DWR servlet -->
  <servlet>
    <servlet-name>dwr-invoker</servlet-name>
    <display-name>DWR Servlet</display-name>
    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
    <init-param>
      <param-name>debug</param-name>
      <param-value>false</param-value>
    </init-param>
  </servlet>

<!-- DWR servlet mapping -->
  <servlet-mapping>
    <servlet-name>dwr-invoker</servlet-name>
    <url-pattern>/dwr/*</url-patter>
  </servlet-mappin>
  


Listing 4. WEB-INF/dwr.xml
                
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
                     "http://getahead.org/dwr//dwr20.dtd">

<dwr>
  <allow>
    <create creator="new" javascript="FileUploadProgressListener">
      <param name="class"
             value="uk.ac.dl.esc.gtg.myportlets.fileupload.FileUploadProgressListener"/>
      <include method="getFileUploadStatus"/>
    </create>
  </allow>
</dwr>
  

Listing 5의 JSP 파일인 fileupload-view.jsp는 DWR이 서버 측에서 파일 업로드 진행을 검색하는 방법을 나타내고 있다. 파일이 선택되고 Upload 버튼이 클릭되면(그림 1), fileupload_ajax_query_upload_status() 메소드가 1초 후에 호출된다. 이 메소드는 FileUploadProgressListener(Listing 2)의 getFileUploadStatus() 메소드를 비동기식 모드에서 호출한다. 여기에 DWR의 강점이 있다. 클라이언트가 서버 측 자바 객체와 통신한다. 응답을 받으면, fileupload_ajax_show_upload_status() 메소드가 호출되어 진행을 리프레시 한다. 파일 업로드가 완수되지 않으면, 업데이트 진행이 2초 후에 검색된다.


Listing 5. 파일 업로드 포틀릿 JSP 파일 -- fileupload-view.jsp
                
<%@ page session="false" %>
<%@ page contentType="text/html" %>
<%@ page import="javax.portlet.PortletURL" %>
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>

<script type="text/javascript"
        src='<%= renderResponse.encodeURL(renderRequest.getContextPath()
				+ "/dwr/interface/FileUploadProgressListener.js") %>'> 
</script>

<script type="text/javascript"
        src='<%= renderResponse.encodeURL(renderRequest.getContextPath()
				+ "/dwr/engine.js") %>'> 
</script>

<script type="text/javascript"
        src='<%= renderResponse.encodeURL(renderRequest.getContextPath()
				+ "/dwr/util.js") %>'> 
</script>

<script type="text/javascript">
  function fileupload_ajax_query_upload_status() {
    FileUploadProgressListener.getFileUploadStatus

                 (fileupload_ajax_show_upload_status);
    return true;
  }

  function fileupload_ajax_show_upload_status(status) {
    if (status == "100")
      document.getElementById("fileupload_progress").innerHTML
                                       ="File successfully uploaded";
    else {
      document.getElementById("progressBar").style.display = "block";
      document.getElementById("fileupload_progress").innerHTML=
                                       "Uploading file: " + status
                                       + "% completed, please wait...";
      document.getElementById("progressBarBoxContent").style.width =
                                       parseInt(status * 3.5) + "px";
      setTimeout(fileupload_ajax_query_upload_status, 2000);
    }

    return true;
  }
</script>

<style type="text/css">
  #progressBar {padding-top: 5px;}
  #progressBarBox {width: 350px; height: 20px; border: 1px insert; background: #eee;}
  #progressBarBoxContent {width: 0; height: 20px; border-right: 1px solid #444;
                                       background: #9ACB34;}
</style>

<h4>File Upload</h4>

<!-- the upload form -->
<% PortletURL pUrl = renderResponse.createActionURL();
 %>
<form action="<%= pUrl.toString() %>"
         enctype="multipart/form-data" method="post"
	 onsubmit="setTimeout('fileupload_ajax_query_upload_status()', 1000)">
	 
  <input type="file" name="fileupload_upload" value="Upload File">
  <input type="submit" value="Upload">
</form>

<%-- file upload progress bar --%>
<div id="fileupload_progress"></div>
<div id="progressBar" style="display: none;">
  <div id="progressBarBoxContent"></div>
</div>
      

Apache Pluto로 파일 업로드 포틀릿 전개 및 테스트 하기

다음 단계는 Apache Pluto 1.0.1로 파일 업로드 포틀릿을 전개 및 테스트 하는 것이다. (주: 이 글에서는 바이너리 버전이 사용되었다.)

코드 컴파일과 전개

Ant 스크립트가 이 글에 포함된 다운로드 가능한 포틀릿 소스 코드에 제공되어, 포틀릿을 컴파일 하고 전개용 .war 파일을 구현할 수 있다. 우선, 소스 코드의 루트 밑에 다음의 라이브러리 파일들을 lib 디렉토리에 복사해야 한다.

  • commons-fileupload-1.2/commons-fileupload-1.2.jar
  • commons-io-1.3/commons-io-1.3.jar
  • commons-logging-1.0.4/commons-logging-1.0.4.jar
  • dwr-2.0.1/dwr.jar
  • portletapi-1.0/portlet.jar
  • servletapi-2.4/servletapi-2.4.jar

이제, ant buildant war를 실행하여 코드를 컴파일 하고, 이에 따라 전개용 .war 파일을 구현할 준비가 되었다. 모든 것이 계획대로 진행된다면, dist 디렉토리 밑에 myportlets-fileupload.war를 찾을 수 있다. 이 단계를 따라서 Apache Pluto 1.0.1에 포틀릿을 전개한다.

  1. Apache Tomcat을 시작하고 http://localhost:8080/pluto/portal에 액세스 한다.
  2. Pluto 스크린의 왼쪽 편에 Admin 링크를 클릭하여 포틀릿을 전개한다.
  3. myportlets-fileupload.war를 배치하고 Submit을 클릭한다.
  4. 포틀릿 제목, 디스크립션, 레이아웃을 정의하고, Submit을 클릭한다.
  5. 디스플레이 된 페이지에 Submit을 다시 클릭한다.

Tomcat을 재 시작 할 것인지, Hot deploy myportlets-fileupload portlet application 링크를 클릭할 것인지를 묻는다. Hot deploy myportlets-fileupload portlet application 링크를 클릭할 것을 권장한다. 이 포틀릿은 그림 1과 같이 로딩된다.


그림 1. Apache Pluto에서 실행되는 파일 업로드 포틀릿
파일업로드 포틀릿

파일 업로드 포틀릿 테스트 하기

포틀릿이 전개되면, 파일을 업로드 할 준비가 된 것이다. 진행 바를 디스플레이 하려면, 포털 서버 외 다른 컴퓨터에서 포틀릿에 액세스 해야 한다. 파일을 업로드 하려면 다음과 같이 한다.

  1. Browse... 버튼을 클릭하여 업로드 할 파일을 선택한다.
  2. Upload 버튼을 클릭하여 선택된 파일을 업로드 한다. 파일 업로드 동안, 진행 바가 디스플레이 및 업데이트 된다. (그림 2).

Pluto가 설치되어 있는 같은 컴퓨터에서 포틀릿을 테스트 해야 한다면, 최대 업로드 사이즈가 20MB로 설정되기 때문에 진행 바를 볼 수 없다. WEB-INF/portlet.xml 파일에서 fileupload_upload_maxsize를 바꿔서 업로드 크기를 변경한다.


그림 2. 파일 업로드 포틀릿 내에 업로드 되고 있는 파일
파일 업로드 포틀릿 내에 업로드 되고 있는 파일

우리 포틀릿에서, 업로드 된 파일은 java.io.tmpdir 밑에 있는 디스크 파일로 저장된다. (예를 들어, $PLUTO_HOME 또는 $CATALINA_HOME 밑의 temp). 실제 웹 애플리케이션에서는 더 많은 프로세싱이 필요하다. 이를 테면, 업로드 된 파일이 앞으로 사용을 대비하여 데이터베이스에 저장되어야 한다. 이미지 파일이라면 웹 브라우저에 디스플레이 될 수 있어야 한다.

기술의 적용

이 글의 기술은 두 개의 서드 파티 데이터 그리드 노드들 간 대형 데이터세트를 관리하기 위해 GridFTP 프로토콜을 활용하는 파일 전송 포틀릿에 성공적으로 적용되었다.

요약

이 글에서는 Ajax를 사용하여 파일 업로드 포틀릿을 개발하여 진행 바를 디스플레이 하는 방법을 설명했다. 진행 리스너를 사용하여 파일 업로드 진행을 서버 측에서 검색하기, 포털 서버에서 DWR을 사용하여 파일 업로드 진행을 클라이언트 측에서 검색하기, 진행 바를 엔드 유저로 렌더링 하는 것 등을 배웠다. 이 포틀릿은 오디오/비디오 파일과 과학 데이터 같은 대형 데이터세트를 공유하는데 유용하다. DWR을 사용하면 JSR 168 포틀릿에서 Ajax를 지원할 수 있다는 것도 설명했다.





위로


다운로드 하십시오

설명이름크기다운로드 방식
파일 업로드 포틀릿 소스 코드wa-aj-dwr.zip13KBHTTP
다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술 얻기

토론


필자소개

Xiaobo Yang

Xiaobo Yang은 영국 CCLRC e-Science Centre, Grid Technology Group의 소프트웨어 개발자이다. 그리드, 협업 가상 연구 환경, 다양한 웹 기술, 그리드 포털, 서비스 지향 아키텍처(SOA)에 관심을 갖고 있다.


Robert Allan

Robert Allan은 영국 CCLRC e-Science Centre, Grid Technology Group을 이끌고 있다. 1980년대 중반부터 물리학을 기반으로, 최신 기술을 사용한 고성능 컴퓨팅 애플리케이션 개발에 관심을 가졌다. 영국의 여러 대형 HPC 및 e-science 프로젝트를 관리한 바 있다. 그리드 상용화에 큰 관심을 갖고 있다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



 


 


 


이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us





위로


IBM and WebSphere are trademarks of IBM Corporation in the United States, other countries, or both. Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both. 기타 회사, 제품, 및 서비스명은 다른 상표나 서비스 마크일 수 있습니다.

developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의