달력

03

« 2010/03 »

  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
  •  
  •  

간혹 사용자 정의 컨트롤(.ascx) 파일에서 처리한 내용을 Page에 바로 출력하는 것이 아니라, 문자열로 받아야 할 경우가 있습니다.
ASP.NET 웹 폼의 경우에는 Page.LoadControl() 과 Control.RenderControl() 메서드를 이용하여 아래와 같은 코드로 사용자 정의 컨트롤이 처리한 내용을 문자열로 받아올 수 있습니다.

Control control = LoadControl("~/MailTemplate.ascx");

 

((MailTemplate)control).DestinationName = "Whistle";

 

StringBuilder stringBuilder = new StringBuilder();

using (StringWriter sw = new StringWriter(stringBuilder))

{

    using (HtmlTextWriter tw = new HtmlTextWriter(sw))

    {

        control.RenderControl(tw);

    }

}

 

string messageContent = stringBuilder.ToString();

ASP.NET 웹 폼은 자체가 Page 클래스를 상속받으므로, TemplateControl.LoadControl() 메서드를 사용할 수 있으므로, 사용자 정의 컨트롤을 로드하고 HtmlTextWriter를 이용하여 컨트롤의 실행된 내용을 문자열로 받아 올 수 있습니다.

ASP.NET MVC는 사용자 정의 컨트롤이 ViewUserContol을 상속받게 되며, MVC Controller는 자체적으로 ViewUserControl에 대한 LoadControl을 제공하지 않습니다,
ViewUserControl 클래스의 인스턴스를 생성은 ViewPage 클래스의 인스턴스 상에서만 가능합니다.

즉, MVC에서 사용자 정의 컨트롤이 생성하는 HTML을 문자열로 받기 위해서는, 가상의 ViewPage의 인스턴스를 생성하고, 그 ViewPage를 기반으로 사용자 정의 컨트롤을 생성한 후 ASP.NET 웹 폼에서와 같은 방법으로 문자열을 받아 올 수 있습니다.

ViewData["UserName"] = "Whistle";

 

ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };

 

viewPage.ViewData = new ViewDataDictionary(ViewData);

viewPage.Controls.Add(viewPage.LoadControl("~/Views/Shared/MailTemplate.ascx"));

 

StringBuilder sb = new StringBuilder();

using (StringWriter sw = new StringWriter(sb))

{

    using (HtmlTextWriter tw = new HtmlTextWriter(sw))

    {

        viewPage.RenderControl(tw);

    }

}

 

string message = sb.ToString();

위와 같은 형식으로 MVC에서도 사용자 정의 컨트롤의 출력 내용을 문자열로 받아와서 처리가 가능합니다.

이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by WHiSTLE

얼마 전 한 신입사원이 데이터베이스에 저장되어 있는 BLOB형태의 이미지 파일을 ASP.NET 웹페이지로 출력하기 위해서, 데이터베이스에서 byte배열을 얻어서 하드디스크에 GUID형태의 이름을 가지는 이미지로 저장한 다음 그 파일을 출력하고, 이미지를 생성할때 마다 파일이 생성될 폴더에 파일 중 생성시간이 하루 이상 지난파일을 삭제하는 로직으로 짜고 있는것을 본적이 있었습니다.

검색엔진에 검색 한번으로 엄청난 양의 레퍼런스 코드가 쏟아져 나올텐데도, 자기 나름대로 계획을 세우고 꿋꿋하게 그걸 구현해 나가는 모습을 보고 얘한테 뭐라고해야하나 말아야하나 고민을 했었더랬습니다.

당시에는 핸들러파일(ashx)파일에서 이미지를 출력하도록하는 방법을 알려주고 끝냈었는데, 오늘 보니 Micorosft에서 ASP.NET Generated Image 라는 상당히 유용해 보이는 컨트롤을 내놓았네요.

서버 컨트롤형태로 구현되어 있고, 각 용도별 구현을 위해서 ImageHandler를 상속받는 ashx 핸들러 파일을 생성하여 컨트롤에 지정하도록 하고 있습니다.
즉, 이미지관련 처리를 위한 라이브러리를 제공하고 그 라이브러리를 이용해서 실제 이미지를 그리는 부분은 사용자에게 맡기는 형태입니다.

예제를 한번 보자면, 페이지에 컨트롤을 올리면
captured_Image.png 
디자인뷰 코드상에서 보면

<cc1:GeneratedImage ID="GeneratedImage1" runat="server" 
    ImageHandlerUrl="~/ImageHandler1.ashx" >
    <Parameters>
      <cc1:ImageParameter Name="Msg" Value="Welcome To CodeDigest" />
      </Parameters>
</cc1:GeneratedImage>
이미지를 처리할 대상을 ImageHandler1.ashx 로 설정하였습니다.
즉, 이미지 출력에 관한 모든 것은 ImageHandler1.ashx가 처리하는 것입니다.
ImageHandler1.ashx는 아래와 같습니다.
<%@ WebHandler Language="C#" Class="ImageHandler1" %>
 
using System;
using System.Collections.Specialized;
using System.Drawing;
using System.Web;
using Microsoft.Web;
 
public class ImageHandler1 : ImageHandler {
    
    public ImageHandler1() {
        // Set caching settings and add image transformations here       
       }
    
    public override ImageInfo GenerateImage(NameValueCollection parameters) {
        // Add image generation logic here and return an instance of ImageInfo
        Bitmap bit = new Bitmap(500, 500);
        Graphics gra = Graphics.FromImage(bit);
        gra.Clear(Color.AliceBlue);
        gra.DrawString(parameters["Msg"], new Font("Verdana", 16), Brushes.Black,0 , 150);
        this.ImageTransforms.Add(new WaterMark());
        return new ImageInfo(bit);
    }
}

위 코드는 새로운 Bitmap을 생성하서 그 안에 매개변수로 넘어온 메시지를 드로잉하여 반환합니다.
그러므로, 이 예제의 결과는 아래와 같습니다.
captured_Image.png[5]

하지만, 지정한 핸들러파일의 GenerateImage메서드의 구현에 따라서 이미지는 어떠한 형태로도 출력이 가능해 집니다.
DB에서 이미지를 불러와서 출력하는 것도 가능하고, 이미지의 리사이즈 및 이미지에 워터마크를 넣고, 테두리를 입히는 작업등 구현에 따라 다른 형태의 이미지를 출력할 수 있을것입니다.

컨트롤의 다운로드는 여기서 가능하시고, .NET Framework 3.5 SP1이 적용되어야 사용이 가능합니다.

좀더 자세한 내용 및 관련 예제은 다음 글 에서 확인이 가능합니다.
New Image Generator control in ASP.Net 3.5

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by WHiSTLE

ASP.NET 2.0에서 파일 다운로드를 구현할때 Respone.WriteFile을 이용해서 다운로드를 구현하였었는데, MSDN에는

큰 파일에 이 메서드를 사용하면 메서드 호출 시 예외가 발생할 수 있습니다. 이 메서드에 사용할 수 있는 파일의 크기는 웹 서버의 하드웨어 구성에 따라 다릅니다. 자세한 내용은 Microsoft 기술 자료에서 812406, "PRB: Response.WriteFile Cannot Download a Large File"을 참조하십시오.

라고 되어있습니다.

즉, 서버의 하드웨어에 따라 다운로드에 대한 한계가 존재한다는 것이겠죠?

 

하지만, HttpResponse 클래스에는 WirtFile메서드외에 TransmitFile메서드도 존재하는데, MSDN설명을 보면

지정된 파일을 메모리에 버퍼링하지 않고 HTTP 응답 출력 스트림에 직접 씁니다.

라고 되어 있습니다.( .NET 2.0에서 추가되었습니다.)

 

즉, 하드웨어의 구성에 관계없이 다운로드가 가능한 것이겠죠?

 

아직 정확한 성능의 차이점은 테스트를 하지않아 알지 못하지만, WriteFile에 대한 문제점을 해결하고자 MS에서 .NET Framework 2.0에서 추가한듯 합니다.(아니면 말구^^)

 

아래는 이미지등의 Internet Explorer자체에서 표시하는 파일형식도 모두 다운로드 대화상자를 이용하여 다운로드하는 코드입니다.

 

    1 Response.ContentType = "image/jpeg";

    2 Response.AppendHeader("Content-Disposition", "attachment; filename=NikeShox.jpg");

    3 Response.TransmitFile(@"D:\My Documents\My Pictures\기타 ScreenShots\042007000046.jpg");

    4 Response.End();

 

HTTP Header에 Content-Dispoition항목에다 attachment라는 값을 할당하였습니다.
Content-Disposition속성에다 attachment속성을 할당하면 브라우저에서 모든 확장자파일에 대하여 다운로드시 다운로드 대화상자를 뜨도록 하는 것이 가능합니다.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by WHiSTLE
몇일전 그동안 사용하던 서버 및 신규 서비스 서버로 사용할 서버 몇 대가 입고되어..
토요일 밤부터 일요일 아침까지 철야 서버 교체 및 서버 확장 작업을 실시 하였습니다.

그 중 그동안 Windows2000, ASP로 사용하던 회사 홈페이지 서버도 교체가 되었습니다.
Windows2003을 설치하고, ASP로 작성된 홈페이지 소스를 옮기고 테스트를 진행하던중
파일 다운로드 기능을 테스트 하던 중 문제가 발생하였습니다.

작은 용량의 첨부파일의 다운로드는 문제가 없었는데, 약 10메가 정도 되는 파일의 다운로드가 되지 않는 것이었습니다.

첨부파일의 다운로드는 ADODB.Stream 객체를 사용하여 파일을 강제로 다운로드 시키는 것이였습니다.

해결 방법을 모색하던 중 IIS 6.0에서는 ASP 에서 기본 4M이상의 파일은 다운로드를 받을 수 없게 설정이 되어 있었습니다.

이는 기본 다운로드 버퍼링 용량을 4MB로 제한한 IIS 6.0의 설정때문이었습니다.
이 IIS 기본 설정은 C:\Windows\system32\inetsrv\MetaBase.xml 에 저장 되어 있으며, 위의 메타베이스 XML파일에서 AspBufferingLimit 값을 원하는 사이즈만큼 늘려주면 해결이 가능합니다.

다운로드제한 : AspBufferingLimit="4194304" - 4MB
업로드제한 : AspMaxRequestEntityAllowed="204800" - 200KB

위 두가지 값을 원하는 용량만큼 설정해주시면 파일 전송에 대한 문제를 해결하실 수 있습니다.


이올린에 북마크하기(0) 이올린에 추천하기(0)
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by WHiSTLE