2009/06/19 - [.NET/Smart Client] - 실전 다중파일업로드 스마트클라이언트 - [2]



상태 변경 작업에 대한 이벤트
 
샘플의 UserControl 에서 업로드 진행 상태에 대한 5가지의 이벤트를 제공한다.
 
UploadStart;                       // 업로드가 시작할때 발생
UploadCompleted;                    // 업로드가 완료되면 발생
UploadFileChanged;                 // 파일별 업로드되면 발생
UploadFilePercentChanged;          // 업로드 진행율이 변경되면 발생
UploadOneFileCompleted;             // 파일 하나가 업로드 완료되면 발생
 
주석에서 보듯이, 업로드 상태의 변경에 따른 이벤트가 발생하도록 하고 있다.
 
이벤트의 발생은 외부에서 다음과 같이 발생하도록 한다.
 
private void OnUploadStart()
{
         if( UploadStart != null )
                  Invoke( UploadStart, null );
}
 
외부 코드에서 += 연산을 통해 이벤트가 구현이 되었을 경우 Invoke 를 통해 이벤트의 Delegate 가 실행되도록 한다.
나머지 Riase 이벤트도 동일하므로 생략한다.
특히 인자를 받는 이벤트도 주의깊게 보도록 하자.
 
 
클래스와 이벤트를 COM 에 노출하기
 
COM 에 노출하기 위한 Attribute 을 선언한다. 이 부분에 대해 실전 스마트클라이언트 그림판 을 참고 하도록 하자.
 
[ClassInterface( ClassInterfaceType.AutoDispatch )]
[ComSourceInterfaces( typeof( IFileUploadComEvents ) )]
[ComVisible(true)]
public partial class FileUploadCtrl : UserControl
{
       …
}
FileUploadCtrl 클래스의 속성 선언
 
[Guid("1DAC6C2D-24C3-4965-B2B6-B7B611C1639C")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface IFileUploadComEvents
{
         [DispId(1)]
         void UploadStart();
      …
}
Interface 를 통한 COM 에 이벤트 노출
 
 
 
스마트클라이언트 엠베디드 페이지
 
드디어 UserControl 이 완성되었다.
알다시피 스마트클라이언트의 어셈블리(*.DLL) 은 브라우져의 object 태그로 엠베디드할 수 있다.
파일이 전송될 때 frmProgress 폼이 뜨게 되고, 업로드 진행상황이 표시되도록 하였다.
하지만, 클래스와 이벤트를 COM 에 노출하였기 때문에, frmProgress 없이도 브라우져의 HTML 로도 진행 상황을 표시할 수 있다.
 
스마트클라이언트, HTML 이 각각 표시하는 업로드 진행율
 
위와 같이 스마트클라이언트가 내뱉는 이벤트를 받을 수 있다.
 
<%@ Page Language="C#" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>다중업로드 스마트클라이언트</title>
         <script type="text/javascript">
                  var cnt = 0;
         </script>
         <script event="UploadStart" for="ctrl">
                  document.getElementById("divUploadStatus").innerText = "업로드 시작";
         </script>
         <script event="UploadCompleted" for="ctrl">
                  document.getElementById("divUploadStatus").innerText = "업로드 완료";
         </script>
         <script event="UploadFileChanged(filename)" for="ctrl">
                  document.getElementById("divFilename").innerText = filename;
         </script>
         <script event="UploadFilePercentChanged(percent)" for="ctrl">
                  document.getElementById("divProgress").style.width = percent + "%";
                  document.getElementById("divProgress").innerText = percent + "%";
         </script>
         <script event="UploadOneFileCompleted" for="ctrl">
                 
         </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
                  <object id="ctrl" classid="Umc.FileuploadCtrl.DLL#Umc.FileUploadCtrl.FileUploadCtrl">
                           <param name="UploadUrl" value="http://umc.pe.kr/Sample/FileUploadSmartClient/FileUpload.aspx" />
                  </object>
                  <p />
                  업로드 상태 : <div id="divUploadStatus"></div>
                  업로드 파일명 : <div id="divFilename"></div>
                  <p />
                  진행율 : <br />
                  <div id="divProgressPanel" style="width:500px;height:20px;">
                           <div id="divProgress" style="width:0%;height:100%;text-align:center;background-color:Red;"></div>
                  </div>
    </div>
    </form>
</body>
</html>
 
FileUploadSmartClient.aspx
 
<script event="UploadFileChanged(filename)" for="ctrl">
         document.getElementById("divFilename").innerText = filename;
</script>
 
C# 코드에서 += 연산을 통해 이벤트를 등록하지만,
자바스크립트로 위와같이 C# 코드처럼 이벤트를 등록할 수 있다.
 
샘플의 WebClient 가 제공하는 이벤트를 통해
 
OnUploadFilePercentChanged(e.ProgressPercentage);
 
InterfaceType Attribute 과 Raise Event 를 호출하였기 때문에, 자바스크립트로 이벤트를 전달 받을 수 있다.
 
 
HTTP 파일 데이터를 받는 페이지
 
아마 샘플의 소스중에 가장 간단한 부분이 될 것 같다.
한번 코드를 보도록 하자.
 
<%@ Page Language="C#" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<script runat="server">
         private void Page_Load(object sender, EventArgs e)
         {
                  if (Request.Files.Count > 0)
                  {
                           string absPath = Server.MapPath(".");
                           string uploadPath = System.IO.Path.Combine( absPath, "Upload" );
                          
                           if( !System.IO.Directory.Exists( uploadPath ) )
                                   System.IO.Directory.CreateDirectory( uploadPath );
                          
                           Request.SaveAs( System.IO.Path.Combine( uploadPath, Request["filename"].ToString()), false);
                  }
         }
         protected override void OnInit(EventArgs e)
         {
                  base.OnInit(e);
                  Server.ScriptTimeout       = 60*1;
         }
</script>
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>제목 없음</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>   
    </div>
    </form>
</body>
</html>
 
HTTP 파일 데이터를 받는 FileUpload.aspx
 
현재 폴더로부터 Upload 폴더에 업로드된 파일을 저장하도록 하였다.
저장될 파일명을 위해 GET 방식으로 저장될 파일명을 넘기도록 하였다.
즉,
 
UploadFile.aspx?filename=a.exe
 
라면 전송된 파일 데이터는 a.exe 로 저장되도록 하였다.
 
아무래도 샘플 페이지이고 외부 업체에 호스팅을 받는 나에게 있어, 트래픽 과부하(아직 그런일은 없다 -_-;) 는 치명적이므로
 
Server.ScriptTimeout   = 60*1;
 
구문을 통해 업로드 되는 파일당 요청제한 시간을 60초로 설정하였다.
때문에, 요청 제한 시간이 초과하게 된다면 “페이지를 찾을 수 없습니다” 또는 “페이지를 요청할 수 없습니다” 라는 오류 또는 메시지가 뜨게 될 것이다.
 
 
마치며
 
아티클이 조금 길어진 감이 없지 않아 있는 것 같다.. 좀더 많은 부분을 전달해 주고 싶었기에, 짧은설명이 아쉬운 부분도 있겠지만, 나름대로 강조한 부분이 잘 전달 되었길 바랄뿐이다 >.,<
언제나 그렇듯, 아티클 하나로 모든 부분을 긁어주진 못할거라고 생각한다.
나조차 아직 많은 부분을 미스하고 넘어가는 경우가 많다. 좋은 정보는 함께 공유했으면 하는 바램이다^^
Posted by 땡초 POWERUMC

댓글을 달아 주세요