login register Sysop! about ME  
qrcode
    최초 작성일 :    2005년 07월 21일
  최종 수정일 :    2005년 07월 21일
  작성자 :    taeyo
  편집자 :    Taeyo (김 태영)
  읽음수 :    22,814

강좌 목록으로 돌아가기

필자의 잡담~

정말로 간만의 강좌이지요? 강좌 업데이트가 빈번하지 않은 점 대단히 죄송합니다. ㅜㅜ

과중한 업무로 인해서리.. 짬내기가 쉽지가 않더라구요. 자그마한 감투들까지 우째우째 얻어쓰다보니... 업무 외에도 외부활동으로도 많은 시간을 써야 해서요 ㅜㅜ..  개인적인 이야기는 요기까지만 하겠습니다. 재미

ASP.NET은 Active Server Pages .NET 이다

ASP나 ASP.NET에 대해 많은 초보자분들이 잘못 알고 있는 것 중에 하나는 이 기술이 실행의 결과로써 HTML을 동적으로 생성(Generating)해 준다고만 알고 있는 것입니다.

물론, 대부분의 경우는 ASP나 ASP.NET의 결과물로 HTML 태그 집합이 생성되기에 이것이 완전히 틀린 말은 아니겠지만, 사실 ASP나 ASP.NET은 단지 그렇게 HTML 결과만을 생성해내는 가벼운 수준의 기술이 아닙니다. ASP나 ASP.NET은 동적인 페이지 기술이며, 그 페이지가 어떤 형태의 데이터가 될 것인지는 얼마든지 개발자의 의도에 따라 바꿀 수 있습니다. 그래서 Active Server Pages 인 것이죠!! 

개발자가 설정만 한다면 ASP 나 ASPX라는 확장자를 갖는 이미지를 만들어 낼 수도 있습니다. 즉, ASP나 ASP.NET 페이지가 이미지 자체로 변환될 수도 있다는 이야기죠. 그 뿐만이 아닙니다. 이들은 원하는 것은 무엇이던 될 수가 있습니다. Zip 파일이나, DOC 문서, 심지어는 PPT 파일이 될 수도 있는 것입니다.

그러면, 이 말이 사실인지 한번 확인해 보는 시간을 가져 보도록 하겠습니다. 그리고, 이러한 지식을 이용하여 파일을 다운로드하는 중간 변환 ASP.NET 페이지도 만들어 보도록 하겠습니다.

우선 어떤 이미지이든지 여러분이 가지고 있는 이미지 중에 하나(JPG 이미지)를 C:\temp 디렉터리에 복사해 주세요. 저의 경우는 maple.jpg 라는 단풍잎 사진을 선택해 보았습니다(이쁘지는 않지만, 제가 직접 찍은 사진입니다). 이미지가 준비되었다면 이제 VS.NET으로 새로운 웹 프로젝트를 만들고, 거기에 새로운 웹 폼 페이지를 하나 추가하도록 하세요. 기본적으로 만들어지는 WebForm1.aspx 페이지를 이용해도 되겠지만, 기왕 만드는거 새롭게 하나 만들어주는 게 좋을 듯 합니다. 저의 경우는 파일의 이름을 AspxImage.aspx 라고 주어보았습니다.

이제 이 AspxImage.aspx 페이지를 이미지로 둔갑시킬 것입니다. 즉, 사용자는 서버에게 AspxImage.aspx라는 페이지를 요청할 것이지만, 우리는 AspxImage.aspx 라는 이름을 갖는 Jpeg 형식의 이미지를 만들어서 그 바이너리 데이터를 브라우저에게 내려보낼 것이라는 이야기이지요~.

말보다는 역시 코드입니다. 일단, AspxImage.aspx 페이지의 HTML 모드에서 <@ Page %> 지시자 구역을 제외한 모든 코드를 전부 삭제하도록 하겠습니다. 그러면, AspxImage.aspx 페이지에는 단지 다음의 코드만이 남게 되겠죠?

<%@ Page language="c#" Codebehind="AspxImage.aspx.cs" AutoEventWireup="false" Inherits="TaeyoAspNet.AspxImage" %>

이제 코드 비하인드 페이지로 이동해 보겠습니다. 그리고, Page_Load 이벤트 처리기를 다음과 같이 작성하세요.

private void Page_Load(object sender, System.EventArgs e)
{
    string imagePath = @"C:\temp\maple.jpg";

    Response.Clear();
    Response.ContentType = "Image/Jpeg";
    Response.WriteFile(imagePath);

    Response.End();
}

위의 코드에서 이미지의 경로인 imagePath 변수의 값은 여러분의 상황에 맞게 알아서 지정하셔야 합니다(여러분이 선택한 이미지 명이 태오와는 다를 수 있으므로). 그리고, 코드를 모두 작성하였다면 페이지를 컴파일하고 실행하여 결과를 확인해 보겠습니다.

그렇습니다. 이미지가 로드되어집니다. 사실, 언뜻 겉으로 보기에는 이 결과가 그리 대단해 보이지 않을 수도 있어요. 브라우저에 단순히 이미지가 출력된 것에 불과하니 말입니이다. 정말로 그렇게 생각하세요? 그렇다면, 이 페이지의 HTML 소스를 살펴 보도록 하죠. 소스를 보기 위해서는 메뉴에서 [보기|소스] 를 선택합니다. 그 메뉴가 비활성화 되어져 있는 것을 확인할 수 있을 것입니다. 그쵸?

그렇습니다. HTML 소스는 볼 수가 없습니다. 왜냐하면, 그런 것이 존재하지 않기 때문입니다!!!!! 그렇다면, 그림에 마우스 우측 클릭을 하여 그림의 [속성]을 살펴보도록 하겠습니다.

그림의 파일명이 AspxImage.aspx인 것을 확인하세요. 그리고, 이 파일의 형식이 JPEG라는 것도 확인하도록 하세요. 분명 파일은 aspx 임에도 파일의 형식은 JPG 파일임을 확인할 수 있을 것입니다. 즉, 이는 ASP.NET 페이지이면서, 동시에 이미지 파일인 것입니다. 이처럼 ASP.NET 페이지는 이미지로써 거듭날 수가 있다는 것이죠.

그렇다면, 이제 소스를 살펴볼 시간입니다. 도대체 코드에서 어떤 마법을 부렸기에 이런 변환이 가능했던 것일까요?

우리가 살펴볼 Page_Load 이벤트 코드의 시작은 응답 개체인 Response의 Clear 메서드를 호출하는 것으로 시작합니다.

Response.Clear();

사실, 이 코드는 생략해도 무방합니다. 아직 그 어떠한 코드도 클라이언트로 내려보내고 있지 않으니 말입니다. 하지만, 확인차원에서 이 코드를 넣는 것은 좋은 습관이라 할 수 있겠습니다. 이는 클라이언트 브라우저로 내려보내기 위해 준비되어져 있을지도 모르는 데이터들을 서버 측에서 소멸하는 역할을 하거든요. 즉, 버퍼를 모두 깨끗하게 비우는 역할을 한다는 것이죠. 버퍼는 클라이언트 브라우저로 내려주기 위해 준비되어지는 데이터의 임시 저장 공간을 말합니다.

버퍼를 깨끗하게 비운 뒤에는, 서버에서 클라이언트에게로 내려보낼 실제 데이터로 버퍼를 채우기 전에 먼저 내려보낼 데이터의 포맷이 어떤 것인지 그 타입을 지정해 주어야 합니다. 그리고, 이를 위해서는 Response 개체의 ContentType 속성을 사용해야 하구요.

Response.ContentType = "Image/Jpeg";

ContentType 속성 값으로 사용할 수 있는 것은 각각의 파일에 대한 MIME 타입입니다. 해서, 예제에서는 JPG 이미지 파일의 MIME 형식인 "Image/JPEG"를 지정해 보았어요. 이 값을 지정하지 않으면 기본적으로 MIME 타입은 "text/html"로 지정되며, 그래서 ASP.NET 페이지들은 ContentType에 대한 별도의 지정이 없어도 HTML 태그 집합을 동적으로 생성하여 브라우저로 내려줄 수 있었던 것입니다.

내려보낼 파일이 어떤 타입인지를 지정했으니 이제는 실제로 JPEG 이미지에 해당하는 파일 스트림 데이터를 브라우저로 내려주어야(즉, 다운로드) 합니다. 기존 ASP에서는 이 부분을 처리할 방법이 없었지만(ADO의 Stream 개체를 통해서 어렵지만 가능하기는 했었죠), ASP.NET에 들어서서는 Response 개체가 제공하는 WriteFile 이라는 특별한 메서드를 통해서 이 부분이 쉽게 가능합니다.

Response 개체의 WriteFile() 메서드는 인자로 지정된 파일의 스트림을 메모리로 읽어와 버퍼에 모두 기록하는 메서드입니다.

Response.WriteFile(imagePath);

그 다음으로 이어지는 코드는 현재까지 버퍼에 저장된 모든 출력을 클라이언트에 실제로 내려 보내고, 페이지 실행을 중지하는 역할을 한다.

Response.End();

이것이 전부입니다. 굳이 순서를 정리해 본다면..

    1)버퍼를 깨끗이 하고 - Response.Clear()
    2)내려보낼 데이터의 형식을 지정하고 - Response.ContentType = MIME Type
    3)버퍼에 바이너리 데이터를 모두 채운 뒤 - Response.WriteFile(imagePath)
    4)그 데이터를 브라우저로 내려보낸다 - Response.End()

그 어떠한 HTML 태그도 필요없습니다. HTML 문자열을 다운로드 하는 것이 아니니 말입니다. 데이터의 타입만 지정하고, 버퍼에 해당 데이터만 로드할 수 있다면, 그 어떠한 파일도 마찬가지로 클라이언트에게 내려보낼 수 있습니다. Zip 파일의 경우도 마찬가지 겠지요. Response.ContentType = "Application/x-gzip" 이라고만 지정하고, 해당 zip 파일을 버퍼에 로드하기만 한다면, 마찬가지로 ASP.NET 페이지는 ZIP 파일이 될 수 있습니다. 물론, 이 경우에는 zip 파일이 브라우저에 로드되는 대신, 파일 다운로드 창이 나타나게 될 것이지만 말입니다.

브라우저가 인식할 수 있는 파일인 GIF, JPG 등의 이미지 파일이나, Text 파일, HTML 파일은 다운로드 창이 별도로 뜨지 않고, 브라우저에 그 결과가 직접적으로 출력(다운로드)되며, ASP나 ASP.NET 페이지의 경우도 서버에서 실행되고 그 결과가 브라우저에 출력됩니다. 이러한 확장자를 가진 파일들은 기본적으로 브라우저에 로드되는 파일들이므로 다운로드 창이 나오지 않고 브라우저에 직접적으로 다운로드 된다는 것을 기억해 주셨으면 하는 쬐깐한 바램이 있습니다.해서, 예제의 경우도 이미지가 다운로드 창으로 나타나는 것이 아니라, 브라우저에 다운로드 된 상태로 출력된 것입니다.

그렇다고, 이러한 파일들을 다운로드 창을 통해서 강제로 다운로드 할 수 없는 것은 아닙니다. 불가능은 일단은 없습니다!!!

파일의 ContentType를 "Application/UnKnown" 으로 강제로 지정하게 되면, 파일의 타입을 막론하고 강제적으로 다운로드 창이 뜨게 됩니다. 즉, 파일 타입을 알 수 없는 것(UnKnown)으로 지정하게 되면, 브라우저는 이 파일을 브라우저에 로드될 수 없는 파일형식이라고 생각하고 무조건 다운로드 창을 띄우기 때문에 그러한 것이죠.

과연 그런지 한번 해 볼까요? Page_Load 이벤트 처리기의 코드를 다음과 같이 수정하고 다시금 실행해 보도록 하세요. ^^ (파란색 폰트 부분이 변경된 부분입니다)

private void Page_Load(object sender, System.EventArgs e)
{
    string imagePath = @"C:\temp\maple.jpg";

    Response.Clear();
    Response.ContentType = "Application/UnKnown";
    Response.WriteFile(imagePath);

    Response.End();
}

이번에는 이미지가 브라우저로 다운로드 되는 것이 아니라, 강제적으로 다운로드 창이 떠서 여러분에게 다운로드의 여부를 물어올 것입니다. 글쵸???

흠이라면 파일의 이름이 원본 이미지의 이름이 아닌 aspx 페이지의 이름으로 나오고 있다는 부분일 것입니다. 대부분의 사용자들은 파일을 maple.jpg라는 원래의 이미지 이름으로 다운로드 할 수 있기를 바랄 것이기에 가급적이면 그러한 이름으로 내려주는 것이 나을 것 같네요. ^^

이 방법을 궁금해 한 분들이 꽤나 있었을 텐데, 방법은 의외로 간단합니다. Content-Disposition 라는 헤더로 attachment;filename=maple.jpg 라는 값을 지정해주면 되는 것이죠. Response 개체의 AddHeader 메서드를 사용해서 다음과 같이 말입니다. (이 방법은 마치 공식처럼 ASP에서도 동일하게 적용됩니다)

Response.AddHeader("Content-Disposition", "attachment;filename= 파일명");

그렇다면, 소스에 그러한 코드를 다음과 같이 추가해 보도록 하겠습니다.

private void Page_Load(object sender, System.EventArgs e)
{
    string imagePath = @"C:\temp\maple.jpg";

    Response.Clear();
    Response.ContentType = "Application/UnKnown";
    Response.AddHeader("Content-Disposition", "attachment;filename=" +
            Path.GetFileName(imagePath));

    Response.WriteFile(imagePath);

    Response.End();
}

소스에서는 파일 명을 코드로 직접 지정하지 않고, Path 클래스의 GetFileName 메서드를 사용해서 동적으로 파일 이름을 얻어와서 지정하고 있습니다.사실, 이번 예제의 경우라면 그 파일 명을 직접 maple.jpg라고 작성해도 될텐데 왜 그렇게 코드를 작성한 것일까요? 그 이유는 실제 개발 시에서는 파일명이 고정적인 경우는 없으며 대부분 코드를 위와 같이 사용하게 될 것이기 때문입니다. 또한, 겸사겸사 Path 클래스의 GetFileName 정적 메서드도 소개하기 위해서 이기도 하구요~~ 하하

파일의 전체 경로에서 파일의 이름을 얻어내는 방법에는 여러 가지가 있겠지만, 그 중 가장 쉬운 방법은 Path 클래스의 GetFileName 정적 메서드를 사용하는 방법입니다. 이 메서드는 인자로 지정된 완전한 경로에서 파일 경로만을 추출해서 반환해 주는 역할을 하거든요.

Path 클래스는 System.IO 네임스페이스에 들어있으므로, GetFileName 메서드를 사용하려면 네임스페이스 참조 구역에 using System.IO; 를 추가해 주어야 하는 것을 잊지 않는 센스!! 필요합니다.

이제 페이지를 다시금 컴파일하고 실행해 보도록 하세요. 다음과 같이 파일 이름이 제대로 나타나면서 다운로드가 되는 것을 볼 수 있을 거예요.

하하하.. 어떻습니까? 잼나죠??그렇습니다. 재미있는 사실을 여러분은 지금 알게 된 것입니다(이미 알고 있었다 하더라도 같이 웃어주는 센스!)1) ASP.NET 페이지는 그 실행 결과로 HTML만을 생성하는 것이 아니라, 바이너리 이미지나 ZIP 파일이 될 수도 있다는 것과 2) 그렇게 생성된 이미지 등의 데이터는 원래 브라우저로 자동 다운로드 되어 출력되는데, 그를 강제로 다운로드 창을 통해서 저장시킬 수도 있다는 사실을 말이죠~

자. 일단 이번 강좌는 여기까지 입니다. 다음 시간에도 이를 응용하여 재미난 이야기를 진행해 볼테니잔뜩 기대하고 계셔 주세요~


authored by


 
 
.NET과 Java 동영상 기반의 교육사이트

로딩 중입니다...

서버 프레임워크 지원 : NeoDEEX
based on ASP.NET 3.5
Creative Commons License
{5}
{2} 읽음   :{3} ({4})