블로그 이미지
내게 능력 주시는 자 안에서 내가 모든것을 할수 있느니라 - 빌립보서 4 : 13 - happydong

카테고리

Happydong (1363)
프로그래밍 (156)
MUSIC (16)
인물 (3)
Utility (10)
세미나 소식&내용 (22)
IT뉴스 (18)
운동 (830)
CAFE (10)
Life (282)
Total
Today
Yesterday



[스텝바이스텝 | HOONS닷넷과 함께하는 닷넷 인사이드 포토라이트(PHOTOLIGHT)]

 

실전 실버라이트 프로그래밍,

포토라이트(PHOTOLIGHT) 만들기!

 



Photo Light 파일업로드 구현

 

파일업로드 어플리케이션 또한 실버라이트로 구현해 봤다. WCF서비스를 이용하니, 다중파일 업로드와 파일업로드 프로그레스바(Progress Bar)를 표시하는데 쉽게 구현 할 수 있었다. 일단 포토라이트에서 파일업로드가 어떤 식으로 작동이 되지는 아래 그림을 통해 순서대로, 간단하게 설명하도록 하겠다.

사용자 삽입 이미지

위 그림에서 노트북으로 표시가 되어 있는 쪽이 클라이언트 PC라고 가정을 하자.

클라이언트는 포토라이트에 파일을 올리기 위해서, 자신이 보유하고 있는 사진을 선택을 할 것이다. 선택이 된 파일은 사용자가 업로드 액션을 주게 될 때, 각 파일 별로 WCF서비스를 호출을 하고, 선택된 파일을 넘겨주게 된다.

WCF서비스에서는 이 파일을 받아서, 파일서버의 해당 루트에 저장을 하게 되는데, 그냥 저장만 시키는 것이 아니라, 쎔네일(Thumbnail) 이미지와 딥줌(DeepZoom)파일들도 만들어 같은 루트 안에 저장을 한다. 이제 대략적으로 포토라이트에서는 어떻게 파일업로드가 되는지 살펴보았으니 이제 실제 구현 코드를 보면서 애기하도록 하겠다


사용자 삽입 이미지

[ 파일업로드 동작 모습 ]

 

위 그림은 포토라이트의 파일업로드 어플리케이션의 모습이며, 프로젝트 구성내용은 아래 그림과 같이 만들어 봤다.


사용자 삽입 이미지


[ 파일업로드 프로젝트 구성 내용 ]

 

위 그림에서 Service References FileUploadService가 참조된 것을 볼 수 있을 거이다. Service를 이용해서 파일을 서버에 업로드를 시킬 수 있는 것이다. Service구현에 대해서는 아래에서 다시 애기하기로 하고, 지금은 저 서비스를 통해서 파일을 업로드 한다고만 알고 있기만 하자.

 각 폴더에 들어 있는 클래스들에 대해서 간단하게 애기하자면, Commands폴더에는 위에서 설명한 Command Pattern 내용 되로 파일업로드에 사용 될 Command를 지정해 둔 클래스를 만들어 두었고, Model폴더에는 파일에 대한 데이터클래스와 파일 업로드 프로바이더(Provider) 정의해 두었다. 그리고 View폴더에는 MVVM패턴 내용과 같이 View ViewModel를 만들어 넣어 두었다. 그럼 이제 파일 업로드에 관련된 주요 코드를 살펴 보도록 하겠다.

먼저, Command 관련 코드에 대해서 보도록 하자.

 

FileUploadCommands.cs

public class FileUploadCommands : Commands

{

public static FileUploadCommands Current { get; private set; }

public static Command FileChoice { get; private set; }

       public static Command FileUpload { get; private set; }

 

static FileUploadCommands()

        {

            Current = new FileUploadCommands();

        }

public FileUploadCommands()

        {

            FileChoice = CreateCommand("FileChoice");

            FileUpload = CreateCommand("FileUpload");

        }

}

 

코드를 보면 Commands를 상속받고 있는 것을 볼 수 있을 것이다. 이는

HugeFlow.CommandPattern.dll를 참조해야지만 상속받을 수 있으며, 이렇게 상속을 받으면 커맨드(Command) 생성을 할 수있게 된다. 필자는 FileChoice FileUpload 두개를 정적으로 생성해 두었다. FileChoice는 파일 선택을 클릭했을때의 커맨드이고, FileUpload는 파일 업로드 클릭했을때의 커맨드이다. 이제 이 커맨드들을 View에서 어떻게 엮어 주고 있는지 코드로 보도록 하겠다.

 

ImagePanelView.xaml

<UserControl x:Class="PhotoLight.FileUploader.ImagePanelView"

          . 중간 생량

xmlns:Command="clr-namespace:HugeFlow.CommandPattern;assembly=HugeFlow.CommandPattern">

 

. 중간 생량

<Button HorizontalAlignment="Right" VerticalAlignment="Stretch"

Width="70" Margin="0,0,5,0" Content="추가" Command:CommandService.Command="FileChoice" Command:CommandService.CommandParameter="Insert" />

 

<Button HorizontalAlignment="Right" VerticalAlignment="Stretch"

Width="70" Margin="0,0,5,0" Content="삭제" Command:CommandService.Command="FileChoice" Command:CommandService.CommandParameter="Delete" />

 

</UserControl>

 

  XAML코드를 보면 먼저 UserControl 엘리먼트(Element) CommandPattern 어셈블리를 설정을 해준다. 그래야 XAML코드에서 Command를 엮을 수 있기 때문이다. 필자는 추가버튼과 삭제버튼 컨트롤을 만들어 아까 위에서 지정한 FileChoice라는 커맨드를 엮어 주었다. Command:CommandService.Command에 미리 만들어 두었던 커맨드 이름을 지정해주면 되는 것이다. 그리고 필요에 따라 매개변수(Parameter)도 같이 지정 할 수가 있는데, 이는 Command:CommandService.CommandParameter에 문자로 지정해 줄 수 있다. 필자는 매개변수로 Insert, Delete라고 지정해 주었다. 이제 이 커맨드를 어디서 어떻게 받는지 알아 보자.

 

 

ImagePanelViewModel.cs

public ImagePanelViewModel()

{

FileUploadCommands.FileChoice.Executed += new EventHandler<HugeFlow.CommandPattern.ExecutedEventArgs>(FileChoice_Executed);

FileUploadCommands.FileUpload.Executed += new EventHandler<HugeFlow.CommandPattern.ExecutedEventArgs>(FileUpload_Executed);

}

 

ImagePanelViewModel이라는 클래스는 ImagePanelView.xaml ViewModel이다. ImagePanelViewModel의 생성자에서 커맨드 이벤트를 생성해 주었다. 위에서도 말했듯 커맨드는 전역에서 사용되어 질수 있으므로 ViewModel에 이벤트를 엮을 수 있다. 이제 커맨드를 어떻게 사용해야 할지 감이 왔을 것이다. 그렇다고 커맨드를 너무 난발하지는 말자. , 무조건 커맨드를 만들지 말자는 애기이다. 예를들면 View에서 VisibilityCollapsed 또는 Visible 하는데 커맨드까지 만들지 말자는 애기다. 이런건 View에서 형태만 바끼는 것이기에 View쪽에서 처리하는게 좋다. 꼭 이점을 주의해서 커맨드를 사용하길 바란다.

 다음으로 파일업로드 코드를 살펴보도록 하자.

 

UploadAgent.cs

public void UploadFile()

{

            if (file != null)

            {

                byte[] buff = new byte[4 * 4096];

                int readbytes = this.file.FileStream.Read(buff, 0, buff.Length);

if (readbytes != 0)

                {

                    this.sent += readbytes;

                    if (this.sent == this.total)

                        isLast = true;

FileUploadData filedata = new FileUploadData()

                    {

                        FileName = file.FileName,

                        FileData = buff,

                        DataLength = readbytes,

                        IsFirst = isFirst,

                        IsLast = isLast,

                        GroupName = file.GroupName

                    };

                    client.SaveFileAsync(filedata);

                    isFirst = false;

file.Uploaded = this.sent;

                }

                else

                {

                    file.FileStream.Dispose();

                    file.FileStream.Close();

                    client.ChannelFactory.Close();

                }

            }

}

 

UploadFile메소드는 WCF서비스에 파일을 업로드하는 메소드이다. 코드를 보면 파일스트림을 읽어, 이를 쪼개서 서비스에 호출을 하고 있음을 알 수 있다. 서비스 호출후 Completed가 일어나면 에러가 없으면 다시 UploadFile메소드를 호출하여 아직 다올리지 않은 파일스트림이 있는지 체크후 다시 서비스를 호출한다. 이렇게 반복되서 파일업로드 진행바에 값을 계속해서 바꿔주게 되는 것 이다. FileUploadData클래스는 서비스에서 생성한 클래스로 업로드를 요청할 때 매개변수(Parameter) 사용이 된다. , 이 클래스에 업로드파일 정보를 지정한후 SaveFileAsync를 호출하고 이 매개변수로 FileUploadData를 지정하면된다.

 이렇게 해서 간단하게 실버라이트에서 파일 업로드 관련 코드를 알아 보았다. 그럼 이제 WCF서비스에서 어떻게 처리하는지 알아 보도록 하자.


Posted by happydong
, |



ㅁ UpdatePanel 안에서 파일 업로드 시켜보기...


UpdatePanel 안에서는 FileUpload Control이 사용이 안됩니다. 그런데도 불고하고 꼭 하고 싶어서.. 예전에 iframe를 이용해서 처리했습니다.
즉, FileUpload Control이 있는 페이지를 하나 따로 만드는 것입니다. 그래서 iframe를 통해서
접근해서 파일을 업로드하는 것이지요~^^

아래는 살짝쿵 만들어 본 소스코드 입니다.

먼저 프로젝트 어떤 페이지들이 있는지 그림들 통해 보도록 하겠습니다.

1. 그림

 

사용자 삽입 이미지


Default.aspx : UpdatePanel로 감싸져 있는 페이지입니다.

FileUp.aspx : FileUpload Control이 있는 페이지입니다.

User_FileUpload.ascx : UserControl 이며, TextBox 와 Button 으로 이루어져 있습니다.


여기에 UserControl이 왜 있을까 하시는 분들을 위해 잠깐 설명하겠습니다. 구지 UserControl를
않만드셔도 상관 없습니다. 이 예제는 전에 어떤분이 UserControl안에 FileUpload 컨트롤을 넣어서 처리할수 있는 방법이 없느냐는 질문에 한번 만들어 본 것입니다. 그래서 구지 UserControl를
사용하지 않으셔도 상관없음을 알려드립니다~^^;;;
오호~그럼 이제 코드가 어떤식으로 짜여져 있는지 보도록 하겠습니다.
일단 Default 페이지부터 보도록 하지요~

////////////////////////////////////////////////////////////////////////////////////////////////

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

 

<%@ Register Src="User_FileUpload.ascx" TagName="User_FileUpload" TagPrefix="uc1" %>

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title>Untitled Page</title>

    <script type="text/javascript">

        function btn01_Click()

        {

            var FileUP = document.getElementById("iframe01").contentWindow.document.getElementById("FilleUpload01");

            FileUP.click();

            var FName = FileUP.value;

            document.getElementById("txtFileName").value = FName;

        }

    </script>

</head>

<body>

    <form id="form1" runat="server">

        <asp:ScriptManager ID="ScriptManager1" runat="server" />

        <asp:UpdatePanel ID="UPDatePanel01" runat="server">

            <ContentTemplate>

                <div id="div_body" style="text-align:center">여기는 Body 입니다.</div>

                <br />

                <uc1:User_FileUpload ID="User_FileUpload1" runat="server" />

                <iframe id="iframe01" src="FileUp.aspx" style="visibility:hidden; height:0px;"></iframe>

                <div id="div1" style="text-align:center">여기는 Body 입니다.</div>

                <br />

            </ContentTemplate>

        </asp:UpdatePanel>

    </form>

</body>

</html>

//////////////////////////////////////////////////////////////////////////////////////////

 비하인드 코드는 각각 하고자 하시는 대로 마음대로 짜시면 될 것 같습니다. 저는 그냥 참고식으
로 만든 예제라 비하인드 코드는 넣지 않았습니다...^^;;
위 코드를 보시면 아주 단순합니다. 그냥 현재 페이지가 Body 부분임을 알리는 글자와
UserControl , 그리고 IFrame 만 있습니다. 물론 IFrame은 Style를 이용해서 안보이게 해주어야
겠지요~^^ 또 제일 위에 Script 코드가 있네요~ 위 Script 코드는 UserControl 에 클릭이벤트를
정의한 겁니다. Script도 간단합니다. 그냥 iframe을 통해서 FileUpload Control에 접급한 것입니
다. 그리고 나서 클릭이벤트를 주고는 그 컨트롤의 value값 즉 사용자가 선택한 파일경로를 가
지오 와서 UserControl에 만들었던 TextBox에 넣어 주는 것입니다.

아래는 UserControl 코드 입니다.

//////////////////////////////////////////////////////////////////////////////////////////

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="User_FileUpload.ascx.cs" Inherits="User_FileUpload" %>

<div id="User_Control" style="text-align:left">여기는 유져 컨트롤 입니다.</div>

<input type="text" id="txtFileName" /><input type="button" id="btn01" value="파일찾기" onclick="btn01_Click()" />

//////////////////////////////////////////////////////////////////////////////////////////


아주 심플 합니다.ㅋ

그럼 이제 FileUpload 컨트롤이 들어 있는 페이지의 소스를 보도록 하겠습니다.

//////////////////////////////////////////////////////////////////////////////////////////

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="FileUp.aspx.cs" Inherits="FileUp" %>

 

<!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>

</head>

<body>

    <form id="form1" runat="server">

    <div>

        <asp:FileUpload ID="FilleUpload01" runat="server" />

    </div>

    </form>

</body>

</html> 

//////////////////////////////////////////////////////////////////////////////////////////

여기도 별거 없네요...말그대로 FileUpload 컨트롤만 있습니다.
너무 샘플해서 설명하기가 부끄럽네요~ㅋ
아래 그림은 실행화면 입니다.

2.그림 (전체 모습)

사용자 삽입 이미지


3.그림(파일찾기 버튼클릭 모습)

사용자 삽입 이미지



4. 그림 (파일을 선택하고 TextBox에 경로가 들어가 모습)

사용자 삽입 이미지


이제 제가 설명한 부분이 대충 감이 오셨으리라 생각이 됩니다. 그럼 비하인드 코드에서 코드를
어떻게 짜야할지도 감이 오시겠군요~^^
이런 방법이 도움이 될지 모르겠습니다~
혹시나 해서 제가 만들 예제 파일도 올리도록 하겠습니다. ^^

Posted by happydong
, |