2008. 12. 20. 03:11
지난번 HttpHelper 클래스를 이어 이번에는 WebClient를 이용한 Downloader 클래스를 만들어 보도록 하겠습니다.

다들 아시겠지만 Downloader 클래스는 실버라이틑 1.1에는 있었지만 실버라이트 2가 나오면서 사라지고 WebClient로 대체가 되었습니다.

물론 바뀐 WebClient가 사용방법이 어려운건 아니지만 좀 더 사용하기 편하게 하기 위해서 WebClient를 이용한 Downloader 클래스를 작성해 보았습니다.

WebClient를 이용한 Downloader 클래스 만들기

1. Downloader 클래스 작성

Downloader 클래스도 HttpHelper 클래스와 마찬가지로 기본 클래스, 이벤트, 다운로드 구분자로 구성 되어 있습니다.

사용할 네임스페이스

using System.Net;
using System.IO;

다운로드 구분

public enum DownloadKind
{
    Text,
    Binary
}

다운로드 구분은 크게 2가지로 텍스트와 바이너리로 구성이 됩니다. 텍스트는 txt, xml, html, js, cs, asp, aspx 같은 순수 텍스트로만 이루어진 파일이며, 바이너리는 wmv, zip, exe 같은 동영상이나 압축파일 등등 텍스트를 제외한 모든 파일이라고 생각해도 좋을거 같습니다.

이벤트 핸들러

public delegate void DownloadCompleteEventHandler(DownloadCompleteEventArgs e);
public class DownloadCompleteEventArgs : EventArgs
{
    public Stream ResultStream { get; set; }
    public string ResultString { get; set; }
    public DownloadCompleteEventArgs(Stream result)
    {
        this.ResultStream = result;
    }
    public DownloadCompleteEventArgs(string result)
    {
        this.ResultString = result;
    }
}
public delegate void DownloadErrorEventHandler(DownloadErrorEventArgs e);
public class DownloadErrorEventArgs : EventArgs
{
    public string Error { get; set; }
    public DownloadErrorEventArgs(string error)
    {
        this.Error = error;
    }
}

이벤트 핸들러는 크게 다운로드 완료 이벤트와 다운로드 에러 이벤트로 구성됩니다.

다음은 기본 클래스의 구성 입니다.

전역

WebClient       m_WebClient;
DownloadKind m_DownloadKind;
Uri                 m_DownloadUri;
public event DownloadCompleteEventHandler DownloadComplete;
private void OnDownloadComplete(DownloadCompleteEventArgs e)
{
    if (this.DownloadComplete != null)
    {
        this.DownloadComplete(e);
    }
}
public event DownloadErrorEventHandler DownloadError;
private void OnDownloadError(DownloadErrorEventArgs e)
{
    if (this.DownloadError != null)
    {
        this.DownloadError(e);
    }
}

다운로드에 필요한 변수와 이벤트를 발생 시키기 위한 내용입니다.

생성자

public Downloader(Uri downloadUri, DownloadKind kind)
{
    m_WebClient = new WebClient();
    m_DownloadKind = kind;
    m_DownloadUri  = downloadUri;
    if (m_DownloadKind == DownloadKind.Binary)
    {
        m_WebClient.OpenReadCompleted += new OpenReadCompletedEventHandler(m_WebClient_OpenReadCompleted);
    }
    else
    {
        m_WebClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(m_WebClient_DownloadStringCompleted);
    }
}

다운로드 구분에 따라서 이벤트를 다르게 생성해 줍니다.

다운로드 시작 함수

public void Start()
{
    if (m_DownloadKind == DownloadKind.Binary)
    {
        m_WebClient.OpenReadAsync(m_DownloadUri);
    }
    else
    {
        m_WebClient.DownloadStringAsync(m_DownloadUri);
    }
}

역시 다운로드 구분에 따라서 Async 함수를 구분해서 실행 합니다.

바이너리 파일 다운로드 완료 이벤트

void m_WebClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    if ((e.Error == null) && (e.Cancelled == false))
    {
        OnDownloadComplete(new DownloadCompleteEventArgs(e.Result));
    }
    else
    {
        OnDownloadError(new DownloadErrorEventArgs(e.Error.Message));
    }
}

텍스트 파일 다운로드 완료 이벤트

void m_WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    if(e.Error == null)
    {
        OnDownloadComplete(new DownloadCompleteEventArgs(e.Result));
    }
    else
    {
        OnDownloadError(new DownloadErrorEventArgs(e.Error.Message));
    }
}

이렇게 해서 Downloader 클래스 작성을 완료 했습니다. 이 클래스에 자신이 원하는 기능을 추가해서 확장 클래스를 작성해서 사용해도 좋을 것입니다.

Downloader 클래스 다운로드



2. Downloader 클래스 사용방법

다운로드 하기

Uri uri = new Uri(http://localhost/DownloaderTest.aspx);
Downloader down = new Downloader(uri, DownloadKind.Text);
down.DownloadComplete += new DownloadCompleteEventHandler(down_DownloadComplete);
down.DownloadError += new DownloadErrorEventHandler(down_DownloadError);
down.Start();

이벤트

void down_DownloadError(DownloadErrorEventArgs e)
{
    txtResult.Text = "에러 : " + e.Error;
}
void down_DownloadComplete(DownloadCompleteEventArgs e)
{
    // 텍스트일 경우
    txtResult.Text = e.ResultString;

    // 바이너리일 경우
    MediaElement media = new MediaElement();
    media.SetSource = e.ResultStream;
    ...
}

도메인 접근시 크로스 도메인이 허용이 안된 사이트는 에러 이벤트를 발생 시킵니다.
이 경우 에러는 Download Failure 라는 에러가 나오네요!!

이것으로 다운로더 클래스 사용 방법도 마치도록 하겠습니다.
아무쪼록 이 글을 보시는 분들께 많은 도움이 되었으면 좋겠습니다.

작성자 : 상현넘™ [http://www.shblitz.net]
Posted by 굿데이