'분류 전체보기'에 해당되는 글 317건

  1. 2012.01.07 C# 인터넷 연결 체크하기
  2. 2012.01.07 자동 업데이트
  3. 2012.01.07 C# 암호화
  4. 2012.01.07 Getting Session State in HttpHandlers (ASHX files)
  5. 2012.01.07 jQuery로 Asp.Net Ajax 사용하기 (Page Method와 Web Service 호출)
  6. 2012.01.07 Sql injection 방어 코딩
  7. 2012.01.07 닷넷에서 CKEditor 설치하기, jQuery 사용하기, 파입업로드, 파일브라우저
  8. 2012.01.07 jQuery를 사용하여 ASP.NET AJAX Web Service 호출하기 예제
  9. 2012.01.07 HttpContext, HttpWebRequest, HttpWebResponse, Application 등의 경로
  10. 2012.01.07 [C#] 제너릭(Generic) : 세번째 이야기
  11. 2012.01.07 [C#] 제너릭(Generic) - 컬렉션의 제너릭 전환 : 두번째 이야기
  12. 2012.01.07 [C#] 제너릭(Generic) - 제너릭 클래스 / 메서드 : 첫번째 이야기
  13. 2012.01.07 [C#] IDictionary 인터페이스 및 간단 HashTable 예제.
  14. 2012.01.07 코딩에 도움이 되는 사이트들
  15. 2012.01.07 MSACCESS MDB 저장프로시저 사용하기
  16. 2012.01.07 Oracle과 MSSQL 데이터타입 비교/매치/차이/치환
  17. 2012.01.07 인덱스의 이해 및 사용법(넌클러스터드 인덱스, 클러스터드 인덱스, 클러스터드 인덱스 + 넌클러스터드 인덱스)
  18. 2012.01.07 Json / JQuery (Ajax)/ Asp.net 3가지를 연동하여 데이터 가져오기
  19. 2012.01.07 WINDOWS SERVER 2008 에 ORACLE 11G 설치
  20. 2012.01.07 오라클 .net 라이브러리
  21. 2012.01.07 [펌]오라클 함수...
  22. 2012.01.07 [펌]오라클의 사용자 함수를 파일로 생성하기
  23. 2012.01.07 윈도우 7에 오라클 11g 설치하기.
  24. 2012.01.07 자료 사이트 : step by step..
  25. 2012.01.06 uploadify
  26. 2012.01.06 [asp.net] ashx 이미지 섬네일
  27. 2012.01.06 [asp.net] 이미지 섬네일
  28. 2012.01.06 C# 이미지 섬네일
  29. 2012.01.06 [.ASHX 파일]jQuery 제너릭 처리기(ashx)로 DB/데이터배이스 받기/사용 핸들러/handler
  30. 2012.01.06 [IO] Stream 의 파생 클래스
posted by 방랑군 2012. 1. 7. 21:01

출처 :  http://blog.naver.com/PostView.nhn?blogId=inidu2&logNo=110032861546&categoryNo=0&parentCategoryNo=33&viewDate=&currentPage=4&postListTopCurrentPage=1&userTopListOpen=true&userTopListCount=10&userTopListManageOpen=false&userTopListCurrentPage=4


인터넷이 연결이 되었는지를 체크하기위한 코드..

마이크로 소프트의 SmartClient Application Building Block 중에서 온라인 체크및 각종 기능이 있다는데.. 
간단히 코드로 확인하는방법이 ..

 

출처 : http://www.c-sharpcorner.com/Code/2003/Aug/CheckInternetConnection.asp

 

using System ;
using
 System.Runtime ;
using System.Runtime.InteropServices ;
 

public class InternetCS
{

//Creating the extern function...
[DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState( out int Description, intReservedValue ) ;

//Creating a function that uses the API function...
public static bool IsConnectedToInternet( )
{

int Desc ;
return InternetGetConnectedState( out Desc, 0 ) ;

}

}

 
 
인터넷이 끊어지는 상황이 발생 중간중간 연결 여부를 체크할 필요가 있어졌다.
연결이 되어 있을때만 실행. 
posted by 방랑군 2012. 1. 7. 21:00

출처 :  http://blog.naver.com/PostView.nhn?blogId=inidu2&logNo=110033716625&categoryNo=0&parentCategoryNo=33&viewDate=&currentPage=4&postListTopCurrentPage=1&userTopListOpen=true&userTopListCount=10&userTopListManageOpen=false&userTopListCurrentPage=4

 

플로우 차트만 보면 무척 간단하다.

업데이트할 내용이 있는지 검사해서 있으면 하고 없으면 말고. 이게 끝이다.

 

자동업데이트 기능은 인터넷의 혜택으로 인해 요즘 프로그램에선 필수 이다.

예제 보고 간단하게 함 따라 해봤는데 나름대로 구미에 맞게 수정하다 보니 제법 그럴싸해졌다.

첨엔 ini 파일을 사용했는데 그거보단 레지스트리가 난거 같아서 레지스트리에 업데이트 정보를 저장해서 사용한다.

DB와 연동해서 프로그램별로 버전관리가 가능하게 했다.

 

 

업데이트 관리 DB – 업데이트 프로그램 통합 관리

3개의 테이블 사용 – 프로그램 관리업데이트 관리업데이트 로그

프로그램 아이디로 구분 하나의 자동업데이트 프로그램을 이용해 모든 프로그램에 적용하여 사용할 수 있다.

설정파일의 프로그램 아이디로 업데이트 관리 테이블을 검색하고 업데이트 내용을 가져와서 해당 파일들을 다운로드 받은 후 업데이트 결과를 업데이트 로그 테이블에 저장해준다.

각 프로그램 단위로 업데이트 상황을 파악할 수 있다.

 

업데이트 파일 검색

버전 정보를 날짜 형식으로 지정해서 현재 버전 보다 높은 버전이 있는지 검색

SELECT TOP 1 IDX, ID, VERSION, CONTENTS FROM UPDATE_LIST WHERE ID=@ID AND VERSION>@VERSION ORDER BY VERSION ASC

업데이트 로그 등록

업데이트할 모든 파일을 다운로드 받은 후 로그 기록

INSERT INTO UPDATE_LOG (UPDATE_IDX, IP, DOWN_DATE) VALUES (@IDX, @IP, GETDATE())

 

 

 

 

 

DB는 아무거나 상관없다.

처음에는 프로그램에서 직접 디비에 접속을 했는데 업데이트 로그 기록하려고 클라이언트의 IP정보를 어떻게 받아오나 고민하다가

좀더 효과적인 방법을 찾았다.

프로그램에서 디비에 직접 접속하는게 아니고 특정 웹페이지로 접속을 해서 업데이트 정보를 가져온다.

가져온 정보로 업데이트 하고 다시 웹페이지를 접속해서 로그를 저장하면 된다.

이렇게 하면 우선 프로그램에 디비 접속 정보가 없어도 되기 때문에 좀더 보안에 안전하다.

그리고 약간의 유연성이 더 있을 것 같다.

 

프로그램이 처음 실행될때 업데이트를 체크하도록 했는데 시작 프로그램에 등록해 놓으니 프로그램이 먼저 시작하고 나서 나중에

인터넷에 연결이 되는 상황이 발생한다.

인터넷 연결이 나중에 되더라도 프로그램이야 잘 돌아가지만 업데이트는 전혀 안되는 상황이 생길 수 있다.

그래서 프로그램 실행 중간에 한번씩 업데이트 체크하는 부분을 추가해야 된다.

 

 

08.08.06 보완사항

메인 프로그램에서 10초에 한번씩 작업을 진행하는데 타이머 위치가 잘못 되서 특정 예외 상황 발생시 거의 무한 루프에 빠져버리는 문제점을 발견했다.

몇일 쉬다가 다시 코드를 보니 원인 찾는데 넘 오래 걸렸다.

타이머 시작 위치 변경 해서 해결 했다.

 

40대의 컴에서 동시에 작업을 하다 보니 디비 서버가 뻗어버렸다.

디비서버 동시 접속수 늘려주고 디비 작업 후 연결 닫는 구문을 모두 추가해주었다.

 

메인 프로그램에서 자동업데이트 체크하는 부분하고 마무리 작업 처리하는 부분만 추가해주면 일단 마무리.

 

 

 

 

자동업데이트 소스

using System;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Web;
using Microsoft.Win32;
using System.Data.SqlClient;
using MySql.Data.MySqlClient;
using System.ComponentModel;

namespace Keyword_Search_Starter
{
    public partial class Starter : Form
    {
        private string sLocalFilePath;          // 실행 경로
        private string sServerFilePath;         // 다운받을 서버주소
        private string sResultMsg;              // 업데이트 체크 결과 메세지(Error, OK)
        private string sID = null;              // 프로그램 아이디
        private string sIDX = null;             // 업데이트 리스트 키값
        private string sAuto = null;            // 자동업데이트 유무(1, 0)
        private string sVersion = null;         // 업데이트 버전 - 6자리날짜(080803)
        private string sStartProgram = null;    // 업데이트 후 실행할 프로그램
        private string sUserIP = null;          // 접속 아이피 로그기록
        private int iUpdateCount = 0;           // 파일 다운로드 숫자 - 전송완료 될 때마다 증가함

        private string sRegKey = "Software\\Pharos";
        private string sUpdateAddr = "http://blog.naver.com/inidu2/Upload/UpdateListView.aspx";

        
        public Starter()
        {
            InitializeComponent();
        }


        #region Starter_Load 레지스트리 정보 읽기
        private void Starter_Load(object sender, EventArgs e)
        {
            sLocalFilePath = AppDomain.CurrentDomain.BaseDirectory;

            // 레지스트리 설정 내용 확인
            RegistryKey reg = Registry.LocalMachine;
            reg = reg.CreateSubKey(sRegKey);

            sID = (string)reg.GetValue("ID", null);
            sStartProgram = (string)reg.GetValue("StartProgram", null);
            sVersion = (string)reg.GetValue("Version", null);
            sAuto = Convert.ToString(reg.GetValue("Auto", null));
            if (reg.GetValue("UpdateAddr", null) != null)
            {
                sUpdateAddr = Convert.ToString(reg.GetValue("UpdateAddr", null));
            }

            lbTitle.Text += " ID : " + sID;

            GetUpdateList();
        }
        #endregion



        #region GetUpdateList() 업데이트 리스트 가져오기
        private void GetUpdateList()
        {
            string path = sUpdateAddr + "?id=" + sID + "&version=" + sVersion;

            try
            {
                HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(path);
                HttpWebResponse hwrp = (HttpWebResponse)hwr.GetResponse();

                Stream strm = hwrp.GetResponseStream();
                StreamReader sr = new StreamReader(strm);

                listView1.Items.Clear();
                int line = 1, n = 1;
                string temp = null;
                while (sr.Peek() > -1)
                {
                    temp = sr.ReadLine();

                    switch (line)
                    {
                        case 1: sResultMsg = temp; break;       // 결과 메시지
                        case 2: sUserIP = temp; break;          // 접속 IP
                        case 3: sIDX = temp; break;             // 업데이트 리스트 키
                        case 4: sVersion = temp; break;         // Version
                        case 5: sServerFilePath = temp; break;  // Path
                        default:                                // File List
                            listView1.Items.Add(n.ToString());
                            listView1.Items[n - 1].SubItems.Add(temp);
                            listView1.Items[n - 1].SubItems.Add("전송대기");
                            n++;
                            break;
                    }

                    line++;
                }
                sr.Close();
                strm.Close();
            }
            catch { }
            finally { }

            // 업데이트 항목이 없으면 무시하고 프로그램 실행
            if (listView1.Items.Count == 0)
            {
                AppStart();
            }
            else
            {
                btnStart.Enabled = false;
                DownLoad();
            }
        }
        #endregion

        

        #region DownLoad() 다운로드
        protected void DownLoad()
        {
            this.Cursor = Cursors.WaitCursor;
            // 다운로드할 파일이 있으면 다운로드
            if (listView1.Items.Count > 0)
            {
                for (int i = 0; i < listView1.Items.Count; i++)
                {
                    string serverFile = sServerFilePath + listView1.Items[i].SubItems[1].Text;
                    string localFile = sLocalFilePath + listView1.Items[i].SubItems[1].Text;
                    try
                    {
                        WebClient webClient = new WebClient();
                        listView1.Items[i].SubItems[2].Text = "전송중";
                        webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
                        webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
                        webClient.DownloadFileAsync(new Uri(serverFile), @localFile);
                        listView1.Items[i].SubItems[2].Text = "전송완료";
                    }
                    catch (Exception ex)
                    {
                        listView1.Items[i].SubItems[2].Text = "전송에러";
                        MessageBox.Show(serverFile + "\r\n" + ex.Message + "\r\n" + ex.StackTrace);
                    }
                }
            }
            this.Cursor = Cursors.Default;
        }
        #endregion



        private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            lbState.Text = e.ProgressPercentage.ToString() + "%";
        }



        #region Completed 전송완료
        private void Completed(object sender, AsyncCompletedEventArgs e)
        {
            iUpdateCount++;
            if (iUpdateCount == listView1.Items.Count)
            {
                this.UpdateLog();
                this.AppStart();
            }
        }
        #endregion



        #region AppStart() 프로그램 실행
        private void AppStart()
        {
            try
            {
                string AppPath = AppDomain.CurrentDomain.BaseDirectory;
                System.Diagnostics.Process ps = new System.Diagnostics.Process();
                ps.StartInfo.FileName = AppPath + sStartProgram;
                ps.Start();

                // 타이머 작업으로 업데이트 감시
                Application.Exit();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\r\n" + ex.StackTrace);
            }
        }
        #endregion
        


        #region UpdateLog() 업데이트 로그 작성 및 버전 정보 업데이트
        private void UpdateLog()
        {
            // 레지스트리 설정 내용 확인
            RegistryKey reg = Registry.LocalMachine;
            reg = reg.CreateSubKey(sRegKey);

            reg.SetValue("Version", sVersion);
            reg.SetValue("LastUpdate", DateTime.Now);



            // 업데이트 로그
            string path = sUpdateAddr + "?mode=log&idx=" + sIDX;

            HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(path);
            HttpWebResponse hwrp = (HttpWebResponse)hwr.GetResponse();

        }
        #endregion
        


        private void btnStart_Click(object sender, EventArgs e)
        {
            DownLoad();
        }

    }
}

[출처] 자동 업데이트|작성자 파로스


 
posted by 방랑군 2012. 1. 7. 20:58

출처 :  http://blog.naver.com/PostView.nhn?blogId=inidu2&logNo=110034898703&categoryNo=0&parentCategoryNo=33&viewDate=&currentPage=4&postListTopCurrentPage=1&userTopListOpen=true&userTopListCount=10&userTopListManageOpen=false&userTopListCurrentPage=4


 
출처: 한빛미디어

저자: 한동훈 

닷넷 프레임워크에서는 암호화와 관련된 많은 API를 제공하고 있다. 데이터를 암호화해서 다른 사람들이 알아볼 수 없게하는 일은 실제로 자주 일어난다. 

인트라넷을 구축하거나, 전자상거래 사이트에서 사용자 정보를 보호하거나, 웹 서비스에서 전송되는 XML 데이터의 내용을 암호화하는 것까지 아주 많은 부분에서 이용된다. 실제로 웹 서비스는 순수 텍스트(plain text)로 데이터가 전송되기 때문에 데이터를 가로채서 그 정보를 알아내는 일은 매우 쉬울 것이다. 이러한 이유로 XML Secuirty와 XML Signature에 대한 표준화 작업이 진행되고 있다. 관심있는 분들은 W3C(http://www.w3c.org)에 방문하기 바란다. 

XML의 내용을 암호화하는 데에는 SAML(The Security Assertions Markup Language) 표기법을 사용하며, 이에 대한 것도 W3C를 방문하기 바란다. 

XML Security & Signature에 대한 실제 구현은 현재 IBM의 XML Security Suite(http://www.alphaworks.ibm.com/tech/xmlsecuritysuite)과 MS의 닷넷 프레임워크가 있다. MS에서는 Web Service Security Language(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsrvspec/html/ws-security.asp)를 참고하기 바란다. 

실제로 여기서 소개하는 내용은 위 참고 자료에 대한 한글판 재탕밖에 되지 않을 것이며, SAML에 대해서는 설명하지 않을 것이다. SAML에 대한 것은 『Programming Web Services with SOAP』, Chapter 7(O'Reilly)을 참고하기 바란다. 

다음은 간단히 SHA1을 이용해서 해시(Hash)를 생성하는 예제다.

이름 : sha1Hash.cs

using System;
using System.IO;
using System.Text;
using System.Security;
using System.Security.Cryptography;

namespace CryptoFilter
{
  public class sha1Hash
  {
    public static void Main()
    {
      sha1Hash app = new sha1Hash();

      app.DoTest();
    }

    public void DoTest()
    {
      SHA1 sha = new SHA1CryptoServiceProvider();

      byte[] data = new byte[3];
      byte[] result = {};

      data[0] = 97;   // ASCII Code 97 = 'a'
      data[1] = 97;
      data[2] = 97;

      result = sha.ComputeHash(data);
      Console.WriteLine("Base64 Encoding : " + Convert.ToBase64String(result));
      Console.WriteLine("ASCII Encoding : \n" + Encoding.ASCII.GetString(result));
    }
  }
}
암호화와 관련된 기능을 이용하려면 System.Security와 System.Security.Cryptography 네임스페이스에 있는 클래스를 이용해야한다. 또한, 암호화는 byte 형태로 되어 있는데 이것을 적절한 문자열(string) 형태로 변환하기 위해 System.Text 네임스페이스를 사용했다. 모든 코드를 입력했으면 다음과 같이 컴파일하여 실행한다.
Csc /out:sha1Hash.exe /target:exe sha1Hash.cs
여기서는 미리 데이터를 입력하고 그에 대한 해시를 생성하는 방법을 사용했다. 아스키(ASCII) 코드 97은 영소문자 'a'이며, 실제로 해시를 생성하기 위해 사용한 입력 데이터는 'aaa'가 된다. 

SHA1 알고리즘으로 생성한 해시는 다음과 같다.

Base64 인코딩을 사용하면 화면에 나타낼 수 있는 문자만을 사용하기 때문에 안전하게 표시할 수 있지만, 직접 문자열로 변환하여 출력하는 경우에는 화면 제어문자와 같은 특수 문자로 인해서 화면이 깨져보일 수 있기 때문에 그 다음 라인에 결과를 출력하도록 했다. 

System.Text.Encoding 클래스를 사용해서 적절한 형태로 바이트 배열을 인코딩해낼 수 있으며, 파일 입출력 처리시에 데이터를 처리하는데도 유용하다. 

간단하게 SHA1 알고리즘을 이용해서 해시를 생성할 수 있는 것을 알 수 있을 것이다. 이것을 VB6에서 작성한다면 대략 3000줄 정도의 코드가 필요하며, 프레임워크가 제공하는 기능에 의해서 단 몇줄만으로 SHA1 암호화 기능을 이용할 수 있으며, 프로그래머는 비즈니스 로직에 더 많이 집중할 수 있을 것이다. 

필자의 경험에 따르면, 부족한 실력으로 어마어마한(?) 암호화를 구현할 수는 없었기 때문에 C 언어와 같은 다른 언어로 작성된 라이브러리를 받아서 VB에서 이용하도록 하기 위한 작업을 한 적도 있고, 몇줄 안되는 XOR 연산을 이용해서 데이터를 암호화하고, 다시 데이터를 복원하기 위해 머리를 쥐어짰던 기억도 있다. 가장 최악의 기억은 MSDN의 Crypto Filter Box 예제마저 제대로 작동하지 않아서 머리를 쥐어뜯은 적도 있고, Win32 Crypt API를 사용하고, 제대로 된 결과를 얻기 위해 많은 시간을 보냈던 기억이 있다. 

다음은 SHA1과 마찬가지로, 간단히 MD5(Message Digest 5) 알고리즘을 이용하여 해시를 생성하는 예제다.
이름: md5Hash.cs

using System;
using System.IO;
using System.Text;
using System.Security;
using System.Security.Cryptography;

namespace CryptoFilter
{
  public class md5Hash
  {
    public static void Main()
    {
      md5Hash app = new md5Hash();

      app.DoTest();
    }

    public void DoTest()
    {
      MD5 md5 = new MD5CryptoServiceProvider();

      byte[] data = new byte[3];
      byte[] result = {};

      data[0] = 97;   // ASCII Code 97 = 'a'
      data[1] = 97;
      data[2] = 97;

      result = md5.ComputeHash(data);
      Console.WriteLine("Base64 Encoding : " + Convert.ToBase64String(result));
      Console.WriteLine("ASCII Encoding : \n" + Encoding.ASCII.GetString(result));
    }
  }
}
SHA1이라는 단어 대신에 MD5를 사용한 것 외에는 큰 차이점이 없을 것이다. 입력 데이터는 같은 데이터를 사용했다. 컴파일은 이전과 같다.
Csc /out:md5Hash.exe /target:exe md5Hash.cs
실행한 결과는 다음과 같을 것이다.

사용자 인증을 웹 서비스로 구현하는 경우에 사용자 ID와 비밀번호를 전송하게 되며, 이 모든 데이터는 일반 텍스트로 전달된다. 즉, 누구나 데이터 패킷을 가로챌 수 있다면 사용자 비밀번호를 쉽게 알아낼 수 있을 것이다. 

데이터를 안전하게 전송할 있도록 위 두 예제를 합쳐서 언제나 사용할 수 있는 하나의 라이브러리로 재작성해보자. 

CryptoFilter.DLL 라이브러리 만들기 

먼저, 이러한 것들을 라이브러리로 편하게 이용할 수 있도록 CryptoFilter.DLL 어셈블리를 작성하도록 하자. 잘 아는 이야기지만, 닷넷에서는 컴포넌트라는 용어 대신에 어셈블리라는 용어를 사용한다.
using System;
using System.IO;
using System.Text;
using System.Security;
using System.Security.Cryptography;
여기서 이용하는데 필요한 각종 네임스페이를 선언하는 부분이다.
namespace CryptoFilter
{
  public class Hash
  {
네임 스페이스와 클래스를 만드는 부분인데, 여기서는 CryptoFilter라는 네임스페이스와 Hash라는 클래스를 작성한다. 코드내에서 이것을 이용하고자 한다면 다음과 같이 사용할 수 있도록 하기 위한 것이다.
CryptoFilter.Hash hash = new CryptoFilter.Hash();
앞에 CryptoFilter를 생략하고 싶다면 코드의 시작에 using CryptoFilter; 를 추가하도록 한다.(하지만, 실제로는 이렇게 추가하지 않으면 원하는 클래스를 찾을 수 없다는 에러가 발생한다)
    public enum HashType
    {
      MD5,
      SHA1
    }

    private string[] InputData = {};
    private string plain = String.Empty;
    private byte[] hashed;
    private byte[] result = new byte[100];
    private bool bSHA1 = false;
    private bool bMD5 = false;
HashType을 선언하고, MD5, SHA1 알고리즘중에 어떤 것을 사용할지를 지정하도록 한다. 이 값에 따라서 bSHA1 또는 bMD5와 같은 불리언(boolean) 타입을 true로 설정하도록 할 것이다. 할당되지 않는 값들에 대해서는 적절한 초기값을 넣어두도록 한다.
private string plain = String.Empty;
문자열 변수에 대해서 값을 할당하지 않는다면 String.Empty과 같은 값을 넣도록 한다.
private string[] InputData = {};
배열에 초기값을 할당하지 않는다는 것을 명시하기 위해 다음과 같이 설정하였다.
    public Hash(HashType hashType, params string[] sInputData)
    {
      if ( hashType == HashType.MD5 )
      {
        bMD5 = true;
      }

      else if( hashType == HashType.SHA1 )
      {
        bSHA1 = true;
      }

      InputData = sInputData;
    } // end of Hash
클래스 이름이 Hash이므로, 여기서 정의한 것은 생성자 Hash를 지정한 부분이다. 생성자 Hash에서는 HashType에 따라서 불리언 값(bMD5, bSHA1)을 true로 설정하도록 한다. 나머지 변수들은 모두 초기값이 false이므로 단 하나의 변수만 true로 설정된다. 

다음으로 해시를 생성할 문자열 값을 입력받아서 전역변수 InputData에 저장한다.
public string Encrypt(bool isBase64)
{
  if(bSHA1)
  {
    SHA1 sha1 = new SHA1CryptoServiceProvider();

    for(int loopctr = 0; loopctr < InputData.Length; loopctr++) plain += InputData[loopctr];
    
    byte[] bSha1Hash = Encoding.ASCII.GetBytes(plain);
    
    result = sha1.ComputeHash(bSha1Hash);

    hashed = result;
  }
  else if(bMD5)
  {
    MD5 md5 = new MD5CryptoServiceProvider();

    for (int loopctr = 0; loopctr < InputData.Length; loopctr++) plain += InputData[loopctr];
    
    byte[] bMD5Hash = Encoding.ASCII.GetBytes(plain);
    
    result = md5.ComputeHash(bMD5Hash);
    
    hashed = result;
  }
각각 설정된 불리언 값(bMD5, bSHA1)에 따라서 입력데이터에 대한 해시를 생성한다. 해시는 바이트 단위로 이루어지기 때문에 입력 받은 문자열에 대해서 루프를 돌면서 한 문자(즉, 한 바이트)씩 해시를 생성하고 이것을 바이트 배열 result에 저장한다. (일반적으로 암호화를 하게되면 그 결과는 원본보다 크기가 커진다)
    if(isBase64)
    {
      return Convert.ToBase64String(hashed);
    }
    else
    {
      return Encoding.ASCII.GetString(hashed);
    }
  }
}
}
이 부분은 전달된 값에 따라서 결과를 Base64 인코딩으로 변환할 것인지, ASCII 형식으로 저장할 것인지를 지정하는 것이다. ASCII 인코딩을 하게되면 특수문자등이 들어가기 때문에 처리하기가 어려워진다. 특히, 웹 서비스의 내용을 암호화하는 경우, XML 컨텐트를 암호화하는 경우, 데이터베이스에 암호화한 내용을 저장하는 경우라면 Base64 인코딩을 사용하기를 권한다.(Base64 인코딩이라는 것은 영문 대소문자와 몇몇 기호들을 합쳐서 64개의 문자로 인코딩한다는 의미다) 

전체소스는 다음과 같다.
이름: CryptoFilter.cs

using System;
using System.IO;
using System.Text;
using System.Security;
using System.Security.Cryptography;

namespace CryptoFilter
{
  public class Hash
  {
    public enum HashType
    {
      MD5,
      SHA1
    } // end of enum HashType

    private string[] InputData = {};
    private string plain = String.Empty;
    private byte[] hashed;
    private byte[] result = new byte[100];
    private bool bSHA1 = false;
    private bool bMD5 = false;

    public Hash(HashType hashType, params string[] sInputData)
    {
      if ( hashType == HashType.MD5 )
      {
        bMD5 = true;
      }

      else if( hashType == HashType.SHA1 )
      {
        bSHA1 = true;
      }

      InputData = sInputData;
    } // end of Hash Constructor

    public string Encrypt(bool isBase64)
    {
      // SHA1 Hash
      if(bSHA1)
      {
        SHA1 sha1 = new SHA1CryptoServiceProvider();

        for(int loopctr = 0; loopctr < InputData.Length; loopctr++)
        {
          plain += InputData[loopctr];
        }
        
        byte[] bSha1Hash = Encoding.ASCII.GetBytes(plain);
        
        result = sha1.ComputeHash(bSha1Hash);

        hashed = result;
      }
      
      // MD5 Hash
      else if(bMD5)
      {
        MD5 md5 = new MD5CryptoServiceProvider();

        for (int loopctr = 0; loopctr < InputData.Length; loopctr++)
        {
          plain += InputData[loopctr];
        }
        
        byte[] bMD5Hash = Encoding.ASCII.GetBytes(plain);
        
        result = md5.ComputeHash(bMD5Hash);
        
        hashed = result;
      } // end of if

      if(isBase64)
      {
        return Convert.ToBase64String(hashed);
      }
      else
      {
        return Encoding.ASCII.GetString(hashed);
      } // end of if

    } // end of function Encrypt

  } // end of class Hash

} // end of namespace CryptoFilter
코드를 모두 입력했다면 다음과 같은 과정을 거친다.
Csc /out:CryptoFilter.dll /target:library CryptoFilter.cs
컴파일이 끝나면 이제 CryptoFilter.DLL 어셈블리가 생성되었을 것이다. 이제 이 어셈블리를 이용하여 해시를 생성하는 프로그램을 작성해보자.
이름: CryptApp.cs

using System;
using CryptoFilter;

public class CryptApp
{
  public static void Main()
  {
    string result = String.Empty;

    Hash hash = new Hash(hash.HashType.MD5, "password");
    result = hash.Encrypt(true);

    Console.WriteLine(result);
  }
}
입력을 모두 했으면 다음과 같이 컴파일한다.
Csc /out:CryptApp.exe /target:exe CryptApp.cs /reference:CryptoFilter.dll
성공적으로 컴파일이 끝나면 CryptApp.exe가 생성된다. 실행한 결과는 다음과 같다.

입력을 모두 했으면 볼 수 있는 것처럼, MD5 알고리즘(hash.HashType.MD5)을 사용하고, 해시를 생성할 입력데이터는 "password"로 하였다. Hash.Encrypt(true)로 하였으므로 결과는 Base64 인코딩될 것이다. 

키를 생성하는 것, XML 컨텐트를 암호화하는 것, 웹 서비스 기반으로 키를 교환하는 것까지 다양한 것들에 대해서 아직 많은 것들이 남아있다. 보다 관심있는 분들은 MSDN이나 관련 문서를 찾아보기바란다.
posted by 방랑군 2012. 1. 7. 20:55

출처 :  http://blog.naver.com/PostView.nhn?blogId=inidu2&logNo=110077631974&categoryNo=0&parentCategoryNo=33&viewDate=&currentPage=2&postListTopCurrentPage=1&userTopListOpen=true&userTopListCount=10&userTopListManageOpen=false&userTopListCurrentPage=2

닷넷에서 jquery를 사용 $.post() 사용하여 ajax로 처리를 하는데 ashx에서 세션 생성이 안되고 읽기만 가능하도록 되어 있어서 한참 동안 삽질.

네이년에도 안나와서 구글 찾아보니 나온다.

 

 

A reminder to myself and others, when you want to get access to your Session State from an ASHX or HttpHandler, you need to implement IReadOnlySessionState:

<% @ webhandler language="C#" class="DownloadHandler" %>

using System;
using System.Web;
using System.Web.SessionState;

public class DownloadHandler : IHttpHandler, IReadOnlySessionState
{
   public bool IsReusable { get { return true; } }
   
   public void ProcessRequest(HttpContext ctx)
   {
       ctx.Response.Write(ctx.Session["fred"]);
   }
}

 

세션을 사용하려면 IReadOnlySessionState, IRequiresSessionState 를 써야 한다.

 

원문 : http://www.hanselman.com/blog/GettingSessionStateInHttpHandlersASHXFiles.aspx

 
posted by 방랑군 2012. 1. 7. 20:53

출처 :  http://blog.naver.com/PostView.nhn?blogId=inidu2&logNo=110093831632&categoryNo=0&parentCategoryNo=33&viewDate=&currentPage=1&postListTopCurrentPage=1&userTopListOpen=true&userTopListCount=10&userTopListManageOpen=false&userTopListCurrentPage=1


환경: jQuery-1.4.2, ASP.NET 2.0, VISUAL STUDIO 2008

파일 첨부: Calling Web Method and Web Service with jQuery.zip

 

jQuery가 제공하는 jQuery.ajax() API를 사용하면 ASP.NET Ajax를 사용하여 웹 서비스나 웹 메서드를 호출 하는 코드를 jQuery를 통하여 구현이 가능하다. (ScriptManager 컨트롤을 사용 하지 않아도 된다)

jQuery.ajax() API는 내부적으로 Ajax(Asynchronous HTTP) 요청을 수행하며 매개변수를 통하여 post get 방식 호출 모두 가능 하다.

 

문법은 아래와 같으며 자세한 내용은 jQuery 사이트의 API 부분을 살펴 보자.

 

 $.ajax(options)

 요청의 생성 방법과 통보 받을 콜백을 제어하고자 전달된 options을 사용하여 Ajax 요청을 전송 한다.

 

 매개변수

 options   (Object) 요청에 대한 매개변수를 정의하는 프로퍼티를 소유한 객체 인스턴스

 

 반환값

 XHR

 

Options 매개변수는 이 함수의 동작을 제어하는 데 다양한 범위의 값을 명시할 수 있다. 모두 살펴 보는 것 보다 자주 쓰이는 항목을 위주로 설명을 하도록 하겠다.

이름

 타입

 설명

 url

  String

  요청 URL

 type

  String

  사용할 HTTP 메서드. 일반적으로 POST나 GET을 사용한다.

 data

  Object

  요청에 전달되는 프로퍼티를 가진 객체. GET 요청이면 데이터는 쿼리 문자열로 제공된다. POST 요청이면 데이터는 요청의 본문으로 제공된다.

 dataType

  String

  응답의 결과로 반환되는 데이터의 종류를 식별하는 키워드. 유효한 값은 다음과 같다. xml, html, json, jsonp, script, text

 timeout

  Number

 Ajax 요청의 제한시간을 밀리초 단위로 설정한다.

 contentType

  String

 요청에 명시되는 콘텐츠 타입.

 success

  Function

 응답이 성공 상태 코드를 반환하면 호출 되는 함수.

 error

  Function

 응답이 에러 상태 코드를 반환하면 호출 되는 함수.

 complete

  Function

 요칭이 완료 되면 호출 되는 함수.

 

 

이제부터 실제 코드를 구현 하여 보자.

우선 웹 사이트를 하나 생성 하고 아래와 같은 과정을 따라 하여 보자.

 

1. jQuery를 사용하여 Page Method 호출하기.

예제 코드: CallingWebMethod.aspx

 

생성 된 웹 사이트에 Page Method 호출 코드를 구현 할 페이지를 하나 만든다.

나는 CallingWebMethod.aspx 페이지를 생성 하였다.

jQuery 라이브러리를 참조 하여야 한다<head> 영역에 아래와 같은 코드를 추가한다.

 

    

<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.js"type="text/javascript"></script>

 

 

코드 비하인드(CallingWebMethod.aspx.cs)로 넘어가서 ASP.NET Ajax를 이용하여 페이지 메서드를 호출 할 때처럼 static으로 메서드를 하나 선언 하고 [WebMethod] Attribute를 부여 한다System.Web.Services네임 스페이스도 추가 하여 주어야 한다.

 

CallingWebMethod.aspx.cs

 

using System.Web.Services;

 

public partial class CallingWebMethod : System.Web.UI.Page

{

[WebMethod]

    public static string GetDate()

    {

        return DateTime.Now.ToString();

    }

}

 

 

CallingWebMethod.aspx 페이지로 돌아와 위의 GetDate() 메서드를 호출 하고 결과를 표시할 UI 영역을 작성 하도록 하자.

날짜를 가져와 표시할 <div> HTML 컨트롤을 하나 배치 한다.

 

CallingWebMethod.aspx

 

<div id="Result">

        Click here for the time.   

</div>

 

 

이제는 실제로 jQuery를 사용하여 Page Method를 호출하고 위의 <div> 에 결과 값을 표시 하는 코드를 자바스크립트로 작성 하도록 하겠다.

 

CallingWebMethod.aspx

 

<script language="javascript" type="text/javascript">

        $(document).ready(function() {

            // Result div onclick 핸들러를 추가하고 핸들러 코드는 페이지 메서드를 호츨 한다.

            $("#Result").click(function() {

                $.ajax({

                    type: "POST",

                    url: "CallingWebMethod.aspx/GetDate",

                    data: "{}",

                    contentType: "application/json; charset=utf-8",

                    dataType: "json",

                    success: function(msg) {

                        // 페이지 메서드 반환 값을 Result div에 삽입한다.

                        $("#Result").text(msg.d);

                    }

                });

            });

        });

</script>

 

 

위의 코드가 복잡해 보일지는 몰라도 사실은 매우 간단하다.

주의해서 보야 할 부분은 $.ajax({ ... }); 이 부분인데 내부 매개 변수는 모두 jQuery.ajax(settings) APIsettings 에 해당 하는 부분이다.

url 옵션에 정확한 페이지명 (페이지명/메소드명)만 지정 하여 준다면 정상적으로 동작 할 것이며 success옵션에 호출 성공시에 처리할 코드를 작성 하여 주면 된다.

 

전체 코드는 첨부 파일의 CallingWebMethod.aspx 페이지를 확인 하여 보자.

 

 

2. jQuery를 사용하여 Web Service 호출하기.

예제 코드CallingWebService.aspx

 

jQuery를 사용하여 웹 서비스를 호출 하는 것 또한 위에서 살펴본 페이지 메서드와 크게 다르지 않으며 다만url 영역에 웹서비스 주소만 적절하게 넘겨 주면 된다.

 

생성 된 웹 사이트에 Web Service 호출 코드를 구현 할 페이지를 하나 만든다.

나는 CallingWebService.aspx 페이지를 생성 하였다.

jQuery 라이브러리를 참조 하는 코드나 UI를 담당할 div는 동일 하다.

 

이제 호출 대상이 될 웹 서비스를 생성 하도록 한다웹 사이트에 WebService.asmx를 추가 한다.

WebService.cs를 열고 호출할 메서드 코드를 작성 한다.

 

메서드 명은 동일 하며 [WebMethod] Attribute 또한 부여한다단 이 웹 서비스를 ajax가 호출 할 수 있도록 하기 위해서는 웹 서비스 생성시에 적용 되어 있는 주석 부분을 제거 하여[System.Web.Script.Services.ScriptService속성이 활성화 되도록 하여야 한다.

 

WebService.cs

 

[WebService(Namespace = "http://tempuri.org/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

// ASP.NET AJAX를 사용하여 스크립트에서 이 웹 서비스를 호출하려면 다음 줄의 주석 처리를 제거합니다.

[System.Web.Script.Services.ScriptService]

public class WebService : System.Web.Services.WebService

{

    public WebService ()

{

        //디자인된 구성 요소를 사용하는 경우 다음 줄의 주석 처리를 제거합니다.

        //InitializeComponent();

    }

 

    [WebMethod]

    public string GetDate()

    {

        return DateTime.Now.ToString();

    }

}

 

 

CallingWebService.aspx 페이지로 돌아와 위 웹 서비스의 GetDate() 메서드를 호출 하는 코드를 작성 하자.

 

CallingWebService.aspx

 

<script language="javascript" type="text/javascript">

        $(document).ready(function() {

            // Result div onclick 핸들러를 추가하고 핸들러 코드는 웹서비스 메서드를 호츨 한다.

        $("#Result").click(function() {

                $.ajax({

                    type: "POST",

                    url: "WebService.asmx/GetDate",

                    data: "{}",

                    contentType: "application/json; charset=utf-8",

                    dataType: "json",

                    success: function(msg) {

                        // 페이지 메서드 반환 값을 Result div에 삽입한다.

                        $("#Result").text(msg.d);

                    }

                });

            });

        });

    </script>

 

 

코드는 url 옵션 영역을 제외 하고 jQuery를 사용하여 Page Method 호출하기에서 살펴 본 것과 거의 동일 하다.

url 옵션에 웹서비스명/메서드명으로 수정 된 것을 주의 깊게 보자.

 

 

이렇게 jQuery를 사용하여 직접 웹 서비스나 페이지 메서드를 호출 하면 약 100KB 이상의 자바스크립트 코드와 3개의 추가적인 HTTP 요청을 제거 할 수 있다.

 

 

위에서 작성 한 모든 코드를 파일 첨부 한다.

Calling Web Method and Web Service with jQuery.zip

 

Reference:

http://api.jquery.com/jQuery.ajax/

http://encosia.com/2008/05/29/using-jquery-to-directly-call-aspnet-ajax-page-methods/

http://encosia.com/2008/03/27/using-jquery-to-consume-aspnet-json-web-services/

 
posted by 방랑군 2012. 1. 7. 20:50


출처 : 
http://blog.naver.com/PostView.nhn?blogId=inidu2&logNo=110122998191&parentCategoryNo=33&viewDate=&currentPage=1&listtype=0&from=postList&userTopListOpen=true&userTopListCount=10&userTopListManageOpen=false&userTopListCurrentPage=1 

테스트를
 여러  하긴 했으나 예상치 못한 예외 상황이 있을수도 있습니다.


고려사항 : 에디터 사용유무 판단, ajax 통신을 위한 json 형태 결과 반환

인코딩 처리는 서버쪽에서만 처리.  폼으로 넘길  하지 않고 디비 저장전에 인코딩 처리.



Sql injection 방어 코딩 – 모든 입력폼값이 적용 

1.     입력

기본적으로 ‘ => &#39;  ,  “ => &quot; 문자만 모두 치환해도 sql 조작이 불가능해짐.

쿼리 실행 전에 특수문자와 html 태그 변환  에디터 사용 여부에 따라 구분해서 인코딩

DB 클래스 내부에서 인코딩되므로 폼값에 별도 처리 없이 그대로 넘김

 

2.     출력 – ajax 통신으로 결과를 json으로 받아서 처리하는 것을 기준.

페이지에 뿌려줄때

-       muse.htmlEncode(data.LIST[i].title) html 인코딩 처리를 해서 html 태그로 페이지가 깨지는 것을 방지

 

폼에 뿌려줄 

-       html 디코딩 처리 $("[name='title']").val(muse.htmlDecode(data.title));

 

에디터에 뿌려줄 때

-      받은 json 을 그대로 입력 $('#contents').val(data.contents);



 

 

 

js

 쿼리 결과를 json으로 받아서 보여줄  사용

 

 

    /**

     * html encode

     */

    htmlEncode: function (str) {

        return str.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/ /g, "&nbsp;").replace(/\n/g, "<br />").replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;");

    },

   

    /**

     * html decode

     */

    htmlDdecode: function (str) {

        return str.replace(/&lt;/g, "<").replace(/&gt;/g, ">");

    }

 

 

 

 

 DB.cs

 디비에 입력, 수정할  필드값 EncodeString하고 가져올   필드 DecodeString, 조건절에 Filtering으로 특수 문자 삭제

 

 

/// <summary>

    /// SQL 인젝션 필터 - Select 에서 조건절 필터링

    /// </summary>

    private static string Filtering(string inputSQL)

    {

        return inputSQL.Replace(":", "").Replace("+", "").Replace(";", "").Replace("--", "").Replace("\"", "");

    }

 

 

    /// <summary>

    /// 데이타베이스 인젝션 방어 문자열 반환

    /// </summary>

    /// <param name="source">원문</param>

    /// <returns></returns>

    public static string EncodeString(string source)

    {

        if (source.IndexOf("&lt;") == -1) // 인코딩 안된 경우

        {

            source = System.Web.HttpUtility.HtmlEncode(source); // ', " 제외

        }

        source = source.Replace("\"", "&quot;").Replace("'", "&#39;");

 

        return source;

    }

 

    public static string DecodeString(string source)

    {

        source = source.Replace("&#39;", "'").Replace("&quot;", "\"").Replace("/", "\\/").Replace("\n", "\\n").Replace("\t", "\\t").Replace("\r", "\\r").Replace("\x08", "\\b").Replace("\x0c", "\\f").Replace("\"", "\\\"");

        if (source.IndexOf("<") == -1) // 에디터에 넘길 경우

        {

            source = System.Web.HttpUtility.HtmlDecode(source);

        }

 

        return source;

    }

 

 

 

posted by 방랑군 2012. 1. 7. 20:49
출처 :  http://inidu2.blog.me/110093858922 

게시판에 에디터 기능을 넣으려고 알아보니 CKEditor가 유명해서 한번 달아 봤다.

기능도 좋고 모양도 깔끔하고 꽤 쓸만한 것 같다.


닷넷 환경이기는 하지만 개발 자체가 jQuery를 사용해서 작업을 하다 보니 실제 닷넷을 쓰는 부분은 디비 처리쪽만 사용을 한다.

그래서 에디터도 닷넷 버전이 따로 제공을 하긴 하지만 닷넷 컨트롤을 사용하는걸 싫어하기 때문에 일반 버전으로 설치했다.

어차피 에디터가 자바스크립트로 이루어져있기 때문에 서버환경이랑 상관은 없다.


게다가 이렇게 작업을 하게 되면 특정 서버와 상관없이 최소한의 수정으로 쉽게 마이그레이션이 가능하다.


작업 순서

1. 다운받기

2. 설치하기

3. 커스터 마이징

4. 파일 업로드 적용


1. 다운받기

http://ckeditor.com/ 이 사이트 가면 데모 버전을 볼 수 있고 다운 받을 수 있다.


2. 설치하기

다운받은 파일을 압축을 풀고 설치할 서버에 업로드 한다.

그리고 에디터를 사용할 페이지를 열어서 해당 스크립트를 추가만 하면 바로 에디터가 적용된다.

업로드한 폴더를 /ckeditor 이라고 가정


1) 기본 설치

head 부분에 스크립트 추가

 <script type="text/javascript" src="/ckeditor/ckeditor.js"></script>



textarea에 에디터 스크립트 적용

<textarea id="editor1" name="editor1">&lt;p&gt;Initial value.&lt;/p&gt;</textarea>

<script type="text/javascript">

CKEDITOR.replace( 'editor1' );

</script>



이렇게만 하면 끝. 이것만으로 아래와 같이 멋지고 강력한 에디터가 적용된다.




2)jQuery 적용하여 설치

head에 /ckeditor/adapters/jquery.js 추가하고 jQuery 형태로 에디터 적용.



<script type="text/javascript" src="/ckeditor/ckeditor.js"></script>

<script type="text/javascript" src="/ckeditor/adapters/jquery.js"></script>

<script type="text/javascript">

$(document).ready(function() {

    $('#editor1').ckeditor(function() { /* callback code */ }, 

    {

        height : 500

    });


    $('#jsonForm').ajaxForm({

        beforeSubmit: validate,        // pre-submit callback

        success     : showResponse,    // post-submit callback

        dataType    : 'json'           // 'xml', 'script', or 'json' (expected server response type)

    });

});

</script>



높이를 500으로 해서 에디터 적용하고 ajaxForm으로 폼 전송



3. 커스터 마이징

툴바에 불필요한 요소는 제거하고 필요한 기능만 선택해서 넣을 수 있다.

전체 적용된 소스

 $(document).ready(function() {

    // 에디터 툴바 옵션

    var myToolbar =  

                [     

                    { name: 'document', items : [ 'Source','-','DocProps','Preview','Print','-','Templates' ]  },

                    { name: 'clipboard', items : [ 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo' ] },

                    { name: 'editing', items : [ 'Find','Replace','-','SelectAll','-','Scayt' ] },

                    { name: 'insert', items : [ 'Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','Iframe' ] },

                            '/',

                    { name: 'styles', items : [ 'Font','FontSize' ] },

                    { name: 'colors', items : [ 'TextColor','BGColor' ] },

                    { name: 'basicstyles', items : [ 'Bold','Italic','Strike','-','RemoveFormat' ] },

                    { name: 'paragraph', items : [ 'NumberedList','BulletedList','-','Outdent','Indent','-','Blockquote','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock' ] },

                    { name: 'links', items : [ 'Link','Unlink' ] },

                    { name: 'tools', items : [ 'Maximize','-','About' ] }

                ];

                

    $('#contents').ckeditor(function() { /* callback code */ }, 

        {

            height : 500,

            toolbar : myToolbar,

            uiColor : '#9AB8F3',

            filebrowserBrowseUrl : 'FileBrowser.aspx?type=image&board_code=' + $('#board_code').val(),

            filebrowserUploadUrl : 'FileUpload.ashx?type=image&board_code=' + $('#board_code').val() + '&board_no=' + $('#no').val() + '&tmp_code=' + $('#tmp_code').val()


        });

});


아래는 위 소스로 적용된 에디터





4. 파일 업로드 적용

파일 업로드는 CKFinder를 사용하면 되는데 라이센스 문제가 좀 있고 분석하기 귀찮아서 비슷한 형태로 그냥 만들어서 사용했다.

첨엔 막막하더니 도움말 좀 뒤져보니 해결이 되었다.

딱 내가 필요한 요소만 있으니 오히려 더 깔끔한 느낌이다.


적용방법

에디터 생성 옵션에 filebrowserBrowseUrl, filebrowserUploadUrl 를 적용해 주면 된다.

말그대로 filebrowserBrowseUrl 는 서버에 있는 파일을 선택해서 에디터에 추가하는 것이고

filebrowserUploadUrl 는 에디터에서 직접 로컬 파일을 선택해서 서버로 올려서 적용하는 것이다.

그러므로 filebrowserBrowseUrl 에는 서버에 있는 파일 리스트를 볼 수 있는 파일을 적어주고

filebrowserUploadUrl 에는 서버로 직접 업로드 해서 저장하는 파일을 적어 주면 된다.


업로드 처리하는 법은 따로 설명하지 않는다.

업로드가 완료되고 나서 에디터에 업로드된 파일을 알려주는 방법은 아래 스크립트를 실행하면 된다.


 HttpContext.Current.Response.Write("<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction('" + CKEditorFuncNum + "', '" + sSaveName + "', '');</script>");


업로드 할때 CKEditorFuncNum, CKEditor, langCode 값이 자동으로 쿼리스트링으로 넘겨진다.

그리고 업로드되는 파일의 폼이름은 upload 이다.


업로드와 마찬가지로 서버에 있는 파일을 선택할 때도 저 스크립트를 그대로 적용해 주면 된다.


 function insertFile(file_name)

{

window.opener.CKEDITOR.tools.callFunction('<%= CKEditorFuncNum %>', file_name, '');

self.close();

}


3번째 파라미터는 메세지로 값이 있을 경우 alert창으로 알려준다.


업로드 창 - 아이프레임 형태로 업로드 함


서버 파일 브라우저 - 게시판별로 이미지를 볼 수 있도록 함.



첨엔 암것도 몰라서 삽질 좀 했는데 다 적용하고 나니 조금은 간단하다. 그만큼 에디터를 잘만들었다는 뜻.

파일 브라우저를 만들다 보니 jQuery가 역시 대단하다는 생각을 한번 더 했다. 

보기엔 별거 아닐 수 있으나 저정도 UI를 간단하게 별 어려움 없이 만들 수 있다.

실제로는 상당히 많은 기능이 들어가 있다.

1. 디비에서 게시판 목록 불러와서 트리형태로 뿌려주기

2. 초기 기본 게시판 이미지 리스트 목록에 뿌려주기(ajax 방식), 리스트 페이징

3. 게시판 선택하면 리스트 다시 불러오고 선택 표시 해주기, 불러올때 로딩 표시

4. 썸네일 표시 100x100 사각형 안에 이쁘게 정렬해서 보여주기



추가로 자바스크립트로 이미지 사이즈 구하기 - 자바스크립트로는 불가능한 줄 알았는데 에디터에서 이미지 이름만으로 사이즈를 가져오는 것을 보고 자바스크립트로도 가능하다는 것을 알았다.


리스트에 바인딩 하면서 이미지가 로딩될때 사이즈를 알아내고 이미지 비율에 따라서 100x100 사각형 박스중간에 정렬 시키기

세로가 더 큰 이미지는 기본적으로 중앙 정렬이기 때문에 문제가 없으나 가로가 더 큰 이미지는 기본 정렬이 상단이라서 적당한 마진을 줘야 박스 중간에 정렬이 가능하다.


     // 이미지 크기 조정

    function imgSize(idx, src)

    {

        var w, h, t;

        $('<img />').attr('src', src).load(function() {

            w = this.width;

            h = this.height;


            $('#size_' + idx).text(w + 'x' + h);

            var $img = $('#img_' + idx);

            if(w < 100 && h < 100) {

                $img.attr({ width: w, height: h });

            } else {

                if(w > h) {

                    t = (100 - (h * 100 / w)) / 2;

                    $img.attr({ width: 100 }).css({ marginTop: t });

                } else {

                    $img.attr({ height: 100 });

                }

            }

        });

    }





에디터 추가 내용은 사이트에 다 나와있다. 물론 눈에 잘 안들어 오긴 하지만....

http://docs.cksource.com/CKEditor_3.x/Developers_Guide



파일 업로드 부분 소스(요청)



 
posted by 방랑군 2012. 1. 7. 19:37

출처 :  http://inidu2.blog.me/110093858922

닷넷을 사용하면서 제일 불편하고 짜증나는 것 중에 하나가 쓸데없는 코드가 너무 많다는 것과 애매모호한 PostBack 이다.

jQuery를 사용하면서 그런 느낌은 더욱 심해졌다.

그래서 사용한 방식이 서버단 처리를 모두 제네릭 처리기로 하였는데 뭔가 다른 방법을 써 보고 싶었다.

MVC가 요즘 뜨는거 같아서 그거로 할까 알아봤지만 뷰가 완전히 독립된 것이 아닌 닷넷 코드 혼합이다.

 

내가 원하는 것은 닷넷 코드가 전혀 들어가지 않은 순수 html + javascript + css로만 구성된 뷰페이지를 구성하는 것이다.

그래서 나온 결론은 웹서비스!

하지만 웹서비스는 기본으로 XML을 지원한다.

JSON을 사용하는 방법을 찾아봤지만 희안하게 한글 자료가 별로 없다. (검색 능력이 떨어지는지 없을리가 없는데~)

암튼 힘들게 찾은 사이트 물론 영어다.

설명은 자세히 되어 있는거 같은데 해석이 안되니~ 다른 한글 자료 찾아보다가 마땅한게 없어서 그냥 영문 사이트 소스보면서 대충 이해했다.

 

생각했던 것 보다는 훨씬 간단했다.

웹서비스 사이트 하나 만들고 거기에 원하는 데이타 뿌려주면 된다.

초간단으로 만든 예제.

이번에도 걸그룹이다. 레인보우~

웹서비스에 Rainbow 클래스를 하나 만들고 GetMember 메소드를 통해서 그룹명과 멤버리스트를 json 형식으로 가져오는 것이다.

사용법만 알면 어려움이 없기 때문에 흐름만 알면 충분하다.

내용이 별로 없어서 이번에도 녹화.

설명글 10번 읽는것보다 작업 내용 한번 직접 보는게 빠르다.

 

닷넷 3.5 이상에서는 보안상 결과값이 {"d": "data"} 형태로 리턴된다. 따라서 스크립트로 처리할때 한번 필터링(dtaFilter) 해준다

 

 

Rainbow.html

 

<!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>
    <title>Rainbow</title>
    
    <script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {

            $("#button").click(function() {
                $.ajax({
                    type: "post",
                    url: "Service1.asmx/GetMember",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    dataFilter: function(data) {
                        var msg;
                        if (typeof (JSON) !== 'undefined' && typeof (JSON.parse) === 'function') {
                            msg = JSON.parse(data);
                        } else {
                            msg = eval('(' + data + ')');
                        }

                        if (msg.hasOwnProperty('d')) {
                            return msg.d;
                        } else {
                            return msg;
                        }
                    },
                    success: function(data) {
                        alert(data.groupName);
                        $("#groupName").text(data.groupName);
                        $("#memberList").text(data.memberList);
                    }
                });
            });
        });
    </script>
    
    <style type="text/css">
    #content { paddding:20px; }
    #groupName { font-weight:bold; font-size:20px; }
    #memberList { color:Blue; }
    </style>
</head>
<body>

    <div id="content">
        <div id="groupName">그룹명</div>
        <div id="memberList">멤버리스트</div>
        <input type="button" value="클릭!" id="button" />
    </div>
</body>
</html>

 

 

Service1.asmx.cs

기본 생성 코드에서   [System.Web.Script.Services.ScriptService] 이부분 주석을 풀어주면 json을 사용할 수 있다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace WebService2
{
    /// <summary>
    /// Service1의 요약 설명입니다.
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // ASP.NET AJAX를 사용하여 스크립트에서 이 웹 서비스를 호출하려면 다음 줄의 주석 처리를 제거합니다. 
    [System.Web.Script.Services.ScriptService]
    public class Service1 : System.Web.Services.WebService
    {

        [WebMethod]
        public string HelloWorld()
        {
            return "Hello World";
        }

        [WebMethod]
        public Rainbow GetMember()
        {
            Rainbow r = new Rainbow();

            r.groupName = "Rainbow";
            r.memberList = "김재경,고우리,김지숙,노을,오승아,정윤혜,조현영";

            return r;
        }
    }


    public class Rainbow
    {
        public string groupName;
        public string memberList;
    }
}


 
posted by 방랑군 2012. 1. 7. 17:28
A
1. WebApplication or WebSite 에서는
this.Context 로 HttpContext 로 제어.

=> this.Context.Request.PhysicalApplicationPath

2. Windows 에서는 HttpRequest 에서 호출으로 제어.

-> Application.StartupPath
 

'PP > TIP' 카테고리의 다른 글

제네릭 처리기를 이용하여 자동가입방지 폼 구현  (0) 2012.01.07
C# 인터넷 연결 체크하기  (0) 2012.01.07
자동 업데이트  (0) 2012.01.07
this.Invoke 관련  (0) 2012.01.06
String <-> byte[] 변환  (0) 2012.01.06
posted by 방랑군 2012. 1. 7. 16:57

출처 :  http://blog.naver.com/PostView.nhn?blogId=alfustnals&logNo=140142248773&categoryNo=41&parentCategoryNo=0&viewDate=&currentPage=1&postListTopCurrentPage=1&from=search

간단예제

  static void Main(string[] args)
 {
    string[] input { "도망노비님의", 
                           "블로그입니다", 
                           "사랑해주세여^^"};

    List<string> listTest = new List<string>(input);

    Console.WriteLine("1번 : \nCapacity: {0}", listTest.Capacity);

    Console.WriteLine();
    foreach (string lst in listTest)
    {
        Console.WriteLine(lst);
    }

    Console.WriteLine("\n");
    listTest.AddRange(listTest);

    Console.WriteLine();


    foreach (string lst in listTest)
    {
        Console.WriteLine("2번 :" + lst);
    }

    Console.WriteLine("\nRemoveRange(2, 2)");
    listTest.RemoveRange(2, 2);

    Console.WriteLine();
    foreach (string lst in listTest)
    {
        Console.WriteLine("3번 : " + lst);
    }

    input = new string[]  { "도망노비님의", 
                                   "블로그입니다", 
                                   "사랑해주세여^^"};

    Console.WriteLine("\nInsertRange(3, input)");
    listTest.InsertRange(3, input);

    Console.WriteLine();
    foreach (string lst in listTest)
    {
        Console.WriteLine(lst);
    }

    Console.WriteLine("\noutput = dinosaurs.GetRange(2, 3).ToArray()");
    string[] output = listTest.GetRange(2, 3).ToArray();

    Console.WriteLine();
    foreach (string lst in output)
    {
        Console.WriteLine(lst);
    }

 }

 MSDN 참고 : http://msdn.microsoft.com/

 
posted by 방랑군 2012. 1. 7. 16:57

출처 :  http://blog.naver.com/PostView.nhn?blogId=alfustnals&logNo=140142234603&categoryNo=41&parentCategoryNo=0&viewDate=&currentPage=1&postListTopCurrentPage=1&from=search

컬렉션의 제너릭 전환 

 제너릭 사용으로 형식의 안정성 명료한 코드 / 수행성능의 향상으로

 제너릭 사용을 권장하고 있다고 한다.

 일반클래스

제너릭 클래스 

 ArrayList

List<T> 

 HashTable

Dictionary<T> 

 SortedList

SortedDictionary<T> 

 Stack

Stack<T> 

 Queue

Queue<T> 

 참조 : 소설 같은 C# 자북 http://www.jabook.com/

 예제_++_

 당산 KH 정보교육원 닷넷 수업떄 들은 자료 참고

 예제_2 : 소설 같은 C# 자북 http://www.jabook.com/ 

 static void Main(string[] args)
{
  SortedDictionary<int, string> mySL=new SortedDictionary<int, string>();
    mySL.Add(5, "소봉");
    mySL.Add(1, "곽정");
    mySL.Add(44,"황용");
    mySL.Add(6, "양과");
    mySL.Add(3, "단예");
    Pring<int, string>("1. SortedDictionary<K, V>의 목록", mySL);

    bool isContains = mySL.ContainsKey(2);
    Console.WriteLine("2. Key 2가 존재하는가? {0} ", isContains);

    Console.WriteLine("3. Key 5의 Value ? {0}", mySL[5]); 
}

private static void Pring<K, V>(string inf, SortedDictionary<K, V> myList)
 {
    Console.WriteLine(inf);

    foreach (KeyValuePair<K, V> kvp in myList)
    {
        Console.Write("\t{0}\t{1}\n", kvp.Key, kvp.Value);
    }

 }
}

[출처] [C#] 제너릭(Generic) - 컬렉션의 제너릭 전환 : 두번째 이야기|작성자 도망노비 
posted by 방랑군 2012. 1. 7. 16:56

출처 :  http://blog.naver.com/PostView.nhn?blogId=alfustnals&logNo=140142225754&categoryNo=41&parentCategoryNo=0&viewDate=&currentPage=1&postListTopCurrentPage=1&from=search

 제너릭(Generic)이란??

 1] 타입 인수를 사용하여 일반화된 클래스나 메서드를 정의하는 기법

 2] 내부 구조나 알고리즘은 동일하게 하되, 취급하는 자료형이 다른 클래스나 메서드가

     필요할때 사용한다.

 3] 일반화된 클래스나 메서드를 정의하는 기법

 4] 코드량 감소 | 캐스팅 하지 않음으로 인한 속도 증가 효과

 제너릭 클래스

 1] 여러 자료형을 가지는 연산에서 컬렉션과 Object 처럼 여러 자료형을 같이 사용할 수

     있게 하는 방법 --> 자료형 한번 주면 따로 형변환 필요없어서 좋다..

 2] 멤버변수 타입을 미리 결정하지 않고, 클래스를 사용 할 떄 결정

 3] 클래스 이름을 여러개 기억 하지 못함.

 일반 클래스 VS 제너릭 클래스 

 using System.Collections;

 namespace genericTest
 {
    class Program
    {
        static void Main(string[] args)
        {
            classTest clsInt = new classTest(44);
            Console.Write("클래스 인트 : ");
            Console.WriteLine((int)clsInt.Value + 44);

            classTest clsbool = new classTest(false);
            Console.Write("클래스 부울 : ");
            Console.WriteLine((bool)clsbool.Value);

            classTest clsStr = new classTest("도망노비님");
            Console.Write("클래스 스트링 : ");
            Console.WriteLine(clsStr.Value.ToString());

          

            genericTest<int> generInt = new genericTest<int>(44);
            Console.Write("제네릭 인트 : ");
            Console.WriteLine(generInt.Value + 44);

            genericTest<bool> generbool = new genericTest<bool>(true);
            Console.WriteLine("제네릭 부울 : " + generbool.Value);

            genericTest<string> generStr = new genericTest<string>("노비");
            Console.WriteLine("제네릭 스트링 : " + generStr.Value);
        }
    }

    class genericTest<T>
    {
        private T value;

        public genericTest(T value)
        {
            this.value = value;
        }

        public T Value
        {
            get { return this.value; }
            set { this.value = value; }
        }
    }

    class classTest
    {
        private object value;
        public classTest(object value)
        {
            this.value = value;
        }
        public object Value
        {
            get { return this.value; }
            set { this.value = value; }
        }

     }
  }

[출처] [C#] 제너릭(Generic) - 제너릭 클래스 / 메서드 : 첫번째 이야기|작성자 도망노비 
posted by 방랑군 2012. 1. 7. 16:55

출처 :  http://blog.naver.com/PostView.nhn?blogId=alfustnals&logNo=140142225754&categoryNo=41&parentCategoryNo=0&viewDate=&currentPage=1&postListTopCurrentPage=1&from=search

ictionary 인터페이스
 

 IDictionary 인터페이스는 그림을 보면 알듯이...;;; ICollection으로부터 파생됬다.

 이 인터페이스의 가장 큰 특징중 하나가 순서에 의해 가던 IList와 달리 흔히 말하는

 키(Key) 와 값(Value)로 대응시켜 데이터를 삽입하고 추출 하는 방법을 제공 한다.

 한마디로 말하면 예전에 내가 해쉬테이블로 예제를 만들어서 공부한것을 올려놧

 었는데 어떤 키를 주면 그 값을 불러올 수 있듯이 데이터에 특정 키를 연결 시켜

 데이터를 추출 한다고 보면 된다.

IDictionary 속성과 함수

 IDictionary 속성

   멤버

                            설명 

 bool IsFixedSize {get;}

 컬렉션의 크기가 정해져 잇는지 검사 

 bool IsReadOnly {get;}

 컬렉션이 읽기 전용인지 검사

 ICollection Key {get;}

 컬렉션 내의 모든 키를 나열

 ICollection Values{get;}

 컬렉션 내의 모든 값을 나열

 IDictionary 함수

              멤버

                  설명 

 void Add(object key, object value)

키/밸류를 전달해 컬렉션에 데이터를 추가

 void Clear()

컬렉션 비움

 bool Contains(object Key)

특정 키가 데이터와 연관 되어있는지 검사

 IDictionaryEnumerator GetEnumerator()

키와값을 나열한다.

 void Remove(object key)

키를 전달하여 데이터를 삭제

 그림 및 내용 데이터 참고 하였습니다.

 ==> http://www.jabook.com/

예제__)

  Hashtable ht = new Hashtable();
   ht.Add("홍길동", "a1");
  ht.Add("홍드로", "b1");
  ht.Add("양현종", null); // 밸류값은 널 가능


  List<string> aList = new List<string>();
  foreach (DictionaryEntry Dic in ht)
  {

   string aKey = (string)Dic.Key;
   string aValue = (string)Dic.Value;
   if (aValue == "a1")
   {
     aList.Add(aKey);
   }
  }     

posted by 방랑군 2012. 1. 7. 15:57

알고리즘 공부하기 [정보 올림피아드 & 알고리즘]
http://www.jungol.co.kr/site/

출처 : http://jeminency.egloos.com/3193932

검색 사이트

http://www.koders.com/
http://www.google.com/codesearch

코드 검색 사이트입니다. 원하는 함수 이름 같은 것을 입력하면 해당되는 소스 파일을 보여주는 식입니다. 물론 모두 오픈소스 소프트웨어들입니다. 함수의 실제 용법을 찾아보거나 할 때는 도움이 되지만... 저는 제 리눅스 계정에 관심있는 오픈소스 패키지들의 소스를 몇십개 갖고 있기 때문에 거기서 find & grep이나 cscope로 찾는 편입니다.


코딩 문제 사이트

프로그래밍 올림피아드라고도 해야 되나... 코딩 문제를 푸는 사이트들입니다.

http://ace.delos.com/usacogate

여기는 과정별로 친절하게 진도를 나가는 스타일입니다 -_-
챕터 1은 좀 쉬운 문제들이고, 그 다음 챕터는 좀 어려운 문제들이고, 그런 식입니다.
문제 풀이는 C/C++, Pascal, Java로 가능합니다. 문제는 입력 파일이 주어지는데 문제에 맞게 입력에 해당하는 출력을 내는 식으로 (원하는 언어로) 코딩을 하여 서브밋하면 서버에서 컴파일하고 테스트하여 결과를 알려줍니다.
제한이 좀 있는데 메모리를 5M 이상 쓰면 안된다거나 실행 시간이 5초 이내여야 된다거나 하는 등입니다.

http://online-judge.uva.es/problemset/

위와 비슷한 사이트이지만 만여개의 문제 중 원하는 걸 풀어볼 수 있습니다. 사용자도 위의 사이트보다는 훨~~씬 많습니다. 거의 이 분야의 공식 사이트라고 보시면 됩니다. 언어는 역시 C/C++, Pascal, Java 등이 가능합니다만...
위의 usacogate 사이트보다는 좀 불친절합니다 -_- 서버에서 테스트시 어떤 입력 데이터를 사용하는지 사용자가 알 수 없다는 점 때문인데 그런 면에서 좀 더 어렵지만 도전해 볼 가치가 훨씬 많지요. 왜 틀렸는지 가르쳐주면 디버깅이 아무래도 많이 쉬워지니까요.

http://codegolf.com/

여기는 문제에 도전해본다는 점은 비슷하지만 위의 두 사이트와는 차원이 좀 다릅니다 -_-;
입력과 출력을 맞게 짜는 것은 동일하다고 할 수 있는데 알고리즘을 따지는게 아니라 소스 코드의 길이를 따집니다. 스페이스, 엔터까지 1바이트를 잡아먹으므로 가독성 따위는 모두 배제하고 최대한 함축된 코드를 짜는 것이 목적입니다.

그래서 여기서는 컴파일 언어를 받아들이지 않고, 스크립트 언어만을 씁니다. 가능한 언어는 Perl, PHP, Python, Ruby의 네 가지입니다.
문제에 따라서는 한 줄로 짜는 사람도 많습니다. 절대적인 강자는 물론 Perl이죠. 다음으로는 Ruby인걸로 알고... C와 비슷한 문법의 PHP나 라인 구분이나 들여쓰기가 엄격한 편인 Python은 사실 불리한 편입니다 -_-;

영어 사이트라 감이 안 오실 수 있는데 이 곳의 문제에 대해 KLDP에 글이 올라와서 인용합니다.

내용을 간단하게 요약하면

(x, y, 문자)쌍 여러개를 입력받아서 정확한 위치에 출력하는 문제입니다.


저의 코드 :
[*$<].map{|s|a=s.split.map{|x|x.to_i};($*[k=a[1]]=$*[k].to_s.ljust 1+k=a[0])[k]=a[2]};puts$*


92바이트로 현재 (루비 부문)19등입니다.

스트링으로 이루어진 배열을 이용했는데요..

이 코드를 좀 더 줄일 수 있을까요??


이런 걸 하면서 노는 사이트입니다 -_-
원래대로는 라인을 나눠야겠지만 '\n'의 바이트를 줄이기 위해서 저런 식으로 짭니다.
저 코드가 궁금하시면 Ruby를 공부하세요 -_-;


그 외

오픈 소스 프로젝트들을 볼 수 있는 사이트들입니다. 다르게 말하면 다른 사람들이 짠 소스를 볼 수 있는 곳이기도 하죠. 이건 정말 큰 축복입니다.

http://sourceforge.net/ : 굳이 설명이 필요없을 정도
http://kldp.net/ : 국내 사이트. 아시는 분도 많겠지만...
http://www.gnu.org/ : 그 유명한 GNU 사이트. gcc, emacs, glibc 등 주옥같은(?) 오픈소스들의 본산.
http://rubyforge.org/ : 루비 프로젝트들이 주로 등록되는 사이트.

그리고 더 이상 생각나는게 별로 없군요. 마지막...

http://robocode.sourceforge.net/

자바로 탱크의 인공지능을 프로그래밍하여 겨루는 사이트입니다. 예를 들면 전진하면서 적을 스캐닝하다가 적을 발견하면 어떤 쪽으로 피하고, 공격을 받으면 어떤 식으로 대처하고 하는 등등을 미리 프로그래밍 해놓는겁니다.
탱크끼리의 전투는 그 로직에 따라 완전 자동으로 이루어지고요. 문제풀이가 위주인 저 위의 사이트들과 달리 게이머의 로직을 직접적으로 겨룬다는 점에서 흥미있습니다(비슷한 류의 다른 사이트도 있었던 거 같은데 기억이 잘...-_-).

...다 쓰고 보니 유명한 곳들 뿐이라 그닥 도움이 될 지는 모르겠군요 -_-;;

'PP > 번외' 카테고리의 다른 글

C# <-> VB.net 코드 변환 사이트  (0) 2012.01.08
C# VS JAVA ~!~!~!  (0) 2012.01.04
posted by 방랑군 2012. 1. 7. 15:54
제대로 설명 나온곳이 없어서... 헤메이다가 사용 성공

찾아보니, 예전 버전(ACCESS 2002?? 2003?? 정확하지 않다.) 에서는 ACCESS에서 저장프로시저가 지원되지 않았다. 하지만 적어도 2007, 2010에서는 저장프로시저와 ADO.net을 사용할 수 있다.

다음 냐옹이의 예제는 2010을 기준으로 간단하게 설명 한다.
(시간은 금이니까~ 날림 설명)

자~ 간단한 설명


위에서 쿼리 마법사, 혹은 쿼리 디자인 아무거나 괜찮다.

1. 쿼리 마법사든, 디자인이든 선택해서 만들고 나면, 쿼리 개체가 생성된다.

2. 생성된 쿼리 개체에는 현재 디자인 보기 혹은 데이터 시트 보기로 되어 있다. 이를 SQL 보기로 전환해준다. 리본메뉴에도 있고, 마우스 우클릭 팝업메뉴에도 잘 나온다.

3. 포풍 쿼리 작성 후 저장

4. 테이블 항목의 관련 없는 개체 탭, 혹은 쿼리탭 에 해당 개체가 추가 된다. [범주 수정하면 수정된 범주에 알아서 들어가겠지]

5. 이를 비주얼 스튜디오에서 확인 해 보면 Select문은 View형태로, Insert, Update, Delete문은 저장프로시저로 들어간 것을 볼 수 있다.



6. ADO.net형식으로 호출 해보면 잘 동작한다.

OleDbConnection Conn = new OleDbConnection();
//mdb
Conn.ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\냐옹.mdb";
OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
dataAdapter.SelectCommand = new OleDbCommand("CameraQuery", Conn);
dataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
DataSet ds = new DataSet();
dataAdapter.Fill(ds);
foreach (DataRow dr in ds.Tables[0].Rows)
{
for (int i = 0; i < dr.ItemArray.Length; i++)
{
Trace.Write(dr[i] + "\t");
}
Trace.WriteLine("");
}
Console.ReadLine();



이상~

posted by 방랑군 2012. 1. 7. 15:51
Data Type Conversion

The gateway converts Microsoft SQL Server data types to Oracle data types as follows:

Table A-1 Data Type Conversions

Microsoft SQL Server Oracle Comment
BIGINT NUMBER(19)
BINARY RAW -
BIT NUMBER(3) -
CHAR CHAR -
DATETIME DATE Fractional parts of a second are truncated
DECIMAL NUMBER(p[,s]) -
FLOAT FLOAT(49) -
IMAGE LONG RAW -
INTEGER NUMBER(10) NUMBER range is -2,147,483,647 to 2,147,483,647
MONEY NUMBER(19,4) -
NCHAR NCHAR -
NTEXT LONG -
NVARCHAR NCHAR -
NUMERIC NUMBER(p[,s]) -
REAL FLOAT(23) -
SMALL DATETIME DATE The value for seconds is returned as 0
SMALL MONEY NUMBER(10,4) -
SMALLINT NUMBER(5) NUMBER range is -32,767 to 32,767
TEXT LONG -
TIMESTAMP RAW -
TINYINT NUMBER(3) -
UNIQUEIDENTIFIER CHAR(36)
VARBINARY RAW -
VARCHAR VARCHAR2 -


Oracle page link
http://download.oracle.com/docs/cd/B19306_01/gateways.102/b14270/apa.htm
posted by 방랑군 2012. 1. 7. 15:50

자, 이제 SQL 서버의 색인을 풀어볼 차례로군요.

약간 어려워도 조금만 참고 함께 이겨나가 보도록 하지요. 그만큼 중요합니다. ^_^


색인의 종류 SQL 서버는 두 가지 종류의 색인이 있습니다. 두가지 뿐이라니 뭔가 기분 좋지요? 그 두가지는 Clustered 인덱스와 Non-Clustered 인덱스 입니다.

각각 한글로는 클러스터된 인덱스 / 클러스터되지 않은 인덱스로 불립니다. -_-;; 늘 그런 것처럼 혼용해서 코난이는 쓸겁니다. 아시져? ^_^;;


인덱스는 분명 만들어야 하는 것입니다. 이 말은

1. 만드는 비용이 있다라는 것이지요.

다음 인덱스는 공간이 필요하다고 했습니다.

2. 디스크 비용이 필요하며 항상 공간 유지를 적절해야 한다는 겁니다.

만들면 끝인가요? 아니죠. 만들었으면?

3. 유지보수에 비용이 필요하겠지요.

인덱스를 만들면 데이터를 조회하는 속도를 높일 순 있지만..

만약 데이터가 삽입 / 수정 / 삭제 된다고 생각해 보세요. 앞에서 본 인덱스의 구조를 변경하면서 재생성 해야겠지요?

4. 데이터 변경이 있을 때 비용이 추가된다는 겁니다.

앞에서 또한 말씀 드렸지만 인덱스를 사용하면 항상 빨라진다고 말씀 안드렸죠.

5. 인덱스는 항상 빠르지 않다.

인덱스를 사용하면 유용한 부분은?

5-1. WHERE절에서 참조되는 컬럼

5-2. 참조키가 설정되어 있는 컬럼

5-3. 참조키는 아니지만 JOIN에 사용되는 컬럼

5-4. 범위 검색이 일어나는 컬럼

5-5. ORDER BY로 정렬 되는 컬럼, GROUP BY로 그룹핑 되는 컬럼

5-6. TOP 구문과 함께 사용되는 SELECT 절

등에서 사용하면 좋습니다.

그렇다면? 어디에 사용하면 바보 될까요?

5-7. WHERE절에서 사용되지 않는 컬럼에는 물론 효과 없음.

5-9. WHERE절에서 변환(함수등이 사용되는)되는 컬럼과 비교시 효과 없음.

5-10. 선택도(찾을 데이터 / 전체 데이터)가 클 경우 효과 적음.

잠시후 말씀 드리겠지만.. 예를 들어 성별 컬럼과 같은 남 / 여 비율적으로 대략 50 : 50 의 구성비가 있는 컬럼이라면? 인덱스의 효과가 떨어지겠죠.

이런 주의 사항이 필요합니다.


자, 이제 인덱스 생성 구문을 실제로 봐 보도록 하지요.

CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name
ON { table | view } ( column [ ASC | DESC ] [ ,...n ] )
[ WITH < index_option > [ ,...n] ]
[ ON filegroup ]

< index_option > ::=
{ PAD_INDEX |
FILLFACTOR = fillfactor |
IGNORE_DUP_KEY |
DROP_EXISTING |
STATISTICS_NORECOMPUTE |
SORT_IN_TEMPDB
}

기분 좋게도 그다지 길지 않지요? 주요한 몇 가지를 말씀 드리면..

UNIQUE를 지정해 고유 인덱스 또는 고유하지 않은 인덱스 생성이 가능합니다.

색인의 종류는 두 가지로 CLUSTERED | NONCLUSTERED 중에 지정이 가능 합니다.

table이나 view에 생성이 가능합니다. SQL 2000의 새로운 기능으로 View에 인덱스 생성이 가능하지요. 뷰 강좌를 참고해 보세요.

컬럼을 ASC 또는 DESC로 정렬해 생성 가능합니다. 특히 클러스터드 인덱스를 생성시 유용하며 ORDER BY 구문과도 밀접합니다. SQL 2000의 새로운 기능입니다.

다음 인덱스 옵션에서

PAD_INDEX는 중간 레벨을 적절히 비워 데이터 삽입 등에 대비하기 위한 것이며

FILLFACTOR는 리프 레벨을 적절히 비워 역시 삽입 등에 대비하는 것입니다.

샘플에서 이야기를 해 드리도록 하지요.

IGNORE_DUP_KEY는 중복되는 값을 무시한다는 의미이구요.

DROP_EXISTING은 이미 존재하는 인덱스가 있으면 제거하고 재생성하라는 의미입니다.

STATISTICS_NORECOMPUTE는 인덱스를 사용할지 안할지 쿼리 최적화기가 결정하는데, 이 근거는 통계치 데이터라는 녀석으로 판단하게 됩니다.

이 통계 데이터는 기본적으로 자동적으로 항상 update 되는데, 이 통계 데이터를 자동 업데이트 하지 말라는 옵션입니다.

SORT_IN_TEMPDB TEMPDB상에서 정렬하라는 옵션입니다. 예를 들어 데이터와 인덱스가 같은 물리적인 디스크에 있고 데이터가 한 1000만건 정도 된다면 인덱스 생성에 대단히 많은 시간이 소요 됩니다.

이때 TEMPDB에서 인덱스 생성시 필요한 정렬작업을 시키고 사용자 데이터베이스의 물리적인 디스크와 TEMPDB 쿨리적인 디스크가 틀리다면 인덱스 생성시 부하를 줄일 순 있지만 TEMPDB에 다른 불필요 공간이 생기니 주의하셔야 하지요.

끝으로 ON filegroup은 인덱스 역시 데이터라고 말씀 드렸습니다. 데이터베이스 강좌에서 filegroup 을 적절히 분산시켜 생성해 속도를 높일 수 있다고 말씀 드린 것처럼 인덱스 역시 적절한 filegroup에 위치시켜 최적의 속도를 낼 수 있게 할 수 있지요.


백견이 불여일타라고 우선 한번 맹거 보도록 하지요.

CREATE DATABASE konanTestDB
GO

USE konanTestDB
GO

--테이블 생성
CREATE TABLE konan_test_table(
konan_id int IDENTITY (1, 1) NOT NULL
, konan_data char (50) NOT NULL
, konan_date char (50) NOT NULL
)
GO

--10000건의 샘플 데이터 삽입
set nocount on
GO

declare @i int
set @i = 0
while @i < 10000
begin
--WAITFOR DELAY '00:00:01'
insert into konan_test_table values
(
@i ,
convert(varchar, datepart(yy, getdate())) + '년 '
+ convert(varchar, datepart(mm, getdate())) + '월 '
+ convert(varchar, datepart(dd, getdate())) + '일 '
+ convert(varchar, datepart(hh, getdate())) + '시 '
+ convert(varchar, datepart(mi, getdate())) + '분 '
+ convert(varchar, datepart(ss, getdate())) + '초 '
+ convert(varchar, datepart(ms, getdate())) + '미리초 '
)
set @i = @i + 1
end
GO
--10초.

set nocount off
GO

--샘플 데이터 조회
SELECT TOP 100 * FROM konan_test_table
SELECT COUNT(konan_id) FROM konan_test_table

대략적인 샘플 데이터 100건과 만건이 잘 들어간게 보일 겁니다.

여기서 어느 정도의 IO 비용이 소요되는지 보도록 할까요?

물론 시간 / IO 비용 모두가 중요하지만 우선 IO 비용만 보도록 하지요.

--IO통계 보기
SET STATISTICS IO ON

SELECT * FROM konan_test_table WHERE konan_id = 5000

--IO통계?

SELECT * FROM konan_test_table WHERE konan_id < 10

--IO통계?

SELECT * FROM konan_test_table WHERE konan_id < 30

--IO통계?

SELECT * FROM konan_test_table WHERE konan_id < 1000

--IO통계?

--IO통계 끄기
SET STATISTICS IO OFF

메시지 부분을 보시면 IO 통계를 확인하실 수 있을 겁니다.

이제 인덱스를 생성해 보도록 하지요.

--간단한 인덱스 생성
CREATE INDEX idx ON konan_test_table (konan_id)
GO

인덱스 생성은 잘 되셨을 거구요. 다시 데이터를 조회해 보도록 할까요?

--IO통계 보기
SET STATISTICS IO ON

SELECT * FROM konan_test_table WHERE konan_id = 5000

--IO통계?

SELECT * FROM konan_test_table WHERE konan_id < 10

--IO통계?

SELECT * FROM konan_test_table WHERE konan_id < 30

--IO통계?

SELECT * FROM konan_test_table WHERE konan_id < 1000

--IO통계?

--IO통계 끄기
SET STATISTICS IO OFF

통계를 봐 보세요. 어떠세요?

아마도 WHERE konan_id < 30 부터 인덱스가 없을 때와 비슷한 수치가 나올 겁니다.

이것은 뭘 말하는 걸까요?
다음처럼 실행계획 표시를 하시거나 또는 컨트롤+K를 눌러 실행계획을 봐 보도록 하지요.

바로 위의 같은 쿼리를 수행해 보면,

위의 그림처럼 실행 계획을 보실 수 있습니다. 중요한건 Index Seek를 했다는 점이지요.

다음 쿼리에서 수행 계획을 보면?

이렇게 konan_id < 30을 봐 보시면 Table Scan을 하는 것을 알 수 있습니다.

분명 어떤 것은 인덱스를 타고 어떤 것은 인덱스를 타지 않지요?

앞에서 말씀드린 건 선택도라고 해서(찾을 데이터수 / 전체 데이터수)로 판단되게 됩니다. 천천히 말씀 드리지요.


다음 인덱스의 정보를 보려면 어떻게 할까요?

--인덱스 정보 조회
sp_helpindex konan_test_table

그러면 인덱스의 정보를 확인할 수 있을 겁니다.

흥미있게 보실 부분으로 인덱스의 종류를 지정하지 않으면? 뒤에서 보시겠지만 넌클러스터드 인덱스로 잡히게 됩니다. 참고하세요.

인덱스의 변경 구문은 없으며 DROP INDEX 구문을 이용해 인덱스를 제거할 수 있습니다.

--인덱스 제거
DROP INDEX konan_test_table.idx

물론 앞에서 말씀드린 CREATE INDEX구문의 DROP EXISTING 구문으로 존재하는 인덱스를 지우고 생성할 수 도 있습니다.


우선 인덱스를 생성하고 돌려는 보셨네요.

이제 본격적인 SQL서버의 인덱스에 대해서 알아 보도록 할까요.

클러스터드 인덱스

클러스터드 인덱스는 간단히 인덱스의 리프레벨이 데이터 페이지와 같은 겁니다.

뭔소리냐구요? 천천히 설명 드리지요.

이런 화면을 생각해 보세요.

클러스터드 인덱스는 물리적으로 행을 재배열해 리프 레벨이 차곡차곡 오른쪽의 데이터 페이지처럼 쌓이게 합니다.

그럼 인덱스를 봐 볼까요?

인덱스가 설정된 컬럼의 값이 순차적으로 재배열되게 되므로 왼쪽에 보시는 인덱스 페이지는 단지 키값과 페이지의 번호만이 지정되게 됩니다.

자, 그럼 우리가 만약 5번 강해원을 찾으려 한다고 생각해 보도록 하지요.

이때는 먼저 클러스터드 인덱스의 값을 보니 4 < 5 < 7 사이가 되므로 4 - 2 인 2번 페이지로 가게 됩니다. 2번 페이지로 가서 바로 5번 강해원을 찾게 되지요.

대략 이러한 그림으로 이루어 지게 되는 겁니다. 만약 12번 김태영을 찾는다면?

이때는 역시 10 < 12 < 13 이므로 4페이지로 가서 12번 김태영을 찾을 수 있게 되겠지요.

이것이 가능한 이유가 뭘까요?

바로 물리적으로 행이 정렬되어 있기 때문에 가능한 거지요. 만약 물리적으로 행이 재배열 되어 있지 않다면? 이런 작업은 불가해 지는 겁니다.
아울러 물리적으로 행들이 재배열 되어 있으므로 범위 검색에 대단히 유용합니다.

이 말은 선택도가 어느 정도 높아도 - 클러스터드 인덱스의 경우 30% 정도도 가능 - 인덱스를 이용해 데이터를 조회할 수 있게 되지요.

아울러 클러스터드 인덱스가 저렇게 테이블에 하나 생성되어 있는데요. 만약 클러스터드 인덱스를 하나 더 테이블에 만들고 싶다면 어떨까요?

안타깝게도 다음번 클러스터드 인덱스는 테이블을 다시 재구성하고 싶겠지만.. 이미 한번 테이블이 정렬된 상태로 재구성되어 있으므로 불가능해 집니다.

오로지 테이블에 단 1개의 클러스터드 인덱스만 생성이 가능하니 주의하셔야 합니다.

그럼 앞의 샘플쿼리를 클러스터드 인덱스로 생성하고 장난을 조금 쳐 볼까요?

--인덱스가 존재하면 지울것
DROP INDEX konan_test_table.idx

--클러스터드 인덱스 생성
CREATE CLUSTERED INDEX idx ON konan_test_table (konan_id)
GO

이렇게 클러스터드 인덱스를 생성할 수 있지요. 그런데 특이하게도 SQL 서버는 클러스터드 인덱스에 대해서 대단히 높은 우선권을 부여합니다.

예를 들어 이럴땐.. 풀스캔을 해도 좋을 것 같은데... 클러스터드 인덱스를 써서 검사할 경우가 있지요.

이는 말씀 드린대로 SQL 쿼리 최적화기가 판단하는데 테이블의 크기가 작거나(로우의 건수가 아닌 전체적인 크기) 또는 클러스터드 인덱스의 키값 컬럼이 작을 경우 종종 발생 합니다.

실제 현업에서는 범위검색에 종종 이 클러스터드 인덱스를 두게 되므로 정상적으로 잘 동작하게 되지요.

또한 클러스터드 인덱스는 비교적 넌클러스터드 인덱스보다 크기가 작습니다. 아울러 클러스터드 인덱스는 크기를 대략적으로 예측할 수 있는 인덱스이기도 하지요.


다음 넌 클러스터드 인덱스를 봐 보도록 할까요?

넌 클러스터드 인덱스

실제 테이블의 데이터가 항상 순차적으로 들어가 있는 것은 아닙니다.

관계형 데이터베이스에서 순차라는 것은 사실 의미가 없습니다. 관계형 데이터베이스의 순차 유지는 오로지 ORDER BY에 적절히 이용되는 컬럼을 잘 구성해야만 하는 것이지요.

예를 들어 실제 진짜 SQL서버에 들어가 있는 테이블의 순서는 다음과 같을 겁니다.

이런 식의 데이터가 실제로 들어가 있게 되지요. 그렇다면 페이지 내부는 어떤 식일까요?

대략적으로 위의 그림과 같은 식의 데이터가 들어가 있게 됩니다.

실질적인 데이터 페이지이지요. 이런 데이터 페이지들의 번호에 클러스터드 인덱스를 만약 생성한다면 어떻게 될까요?

이럴 경우는 RID라는 녀석이 필요하게 됩니다. 간단히 RID는 로우의 구별하는 특정 값이라고 생각하시면 됩니다.

넌 클러스터드 인덱스는 바로 이 RID를 가지고 데이터 페이지를 포인팅 하게 되지요.

RID 샘플을 보시면 다음과 같은 식입니다.

여기서 RID의 첫번째 1은 화일 그룸을 의미하게 됩니다.

그 다음 숫자는 데이터 페이지 번호이며 마지막 세번째 숫자는 페이지 옵셋으로 정확히 페이지의 한 로우를 포인팅(Pointing)하게 되지요.

또한 이 인덱스 페이지는 다음과 같은 형식으로 분할 되겠지요.

이러한 형식이 넌클러스터드 인덱스에서 과연 어떻게 사용 될까요?

실제 구조를 그려 보도록 하지요.

이러한 식으로 생성이 되게 됩니다.

루트 레벨은 인덱스 페이지 7이며, 중간 레벨은 엔덱스 페이지 1,2,3,4 이고, 실제 데이터페이지는 1,2,3,4,5 데이터 페이지가 되지요.

자, 값을 네비게이션 해 보도록 합시다. 만약 제가 3번 이승용을 찾으려 한다고 생각해 보지요.

1 < 3 < 5 이므로 1페이지로 가야 겠지요? 같더니 3은 4페이지 2번째 로우에 있다고 합니다. 바로 4페이지로 가서 두번째 로우를 컨택하는 거지요.

또한 만약 8 차영인을 찾으려 한다면

5 < 8 < 9 이므로 인덱스페이지 2로 가서 8 차영인을 보니 1-3-2라고 되어 있습니다. 데이터 페이지 3의 2번째 로우를 포인팅 하게 되지요.

이것이 넌클러스터드 인덱스 입니다.

넌클러스터드 인덱스는 이렇게 포인팅 정보를 가지게 되므로 인덱스의 크기가 커지게 됩니다.
아울러 선택도가 높으면 바로 쿼리 최적화기는 이 넌클러스터드 인덱스를 사용하지 않게 되지요. 일반적으로 3% 이내 정도면 이 넌클러스터드 인덱스를 사용하지 않게 됩니다.

넌클러스터드 인덱스는 데이터페이지를 물리적으로 재배열하지 않으므로 여러개의 인덱스를 생성할 수 있습니다. 최대 생성 가능 갯수는 249개 입니다.

두 차이를 비교한다면 다음과 같겠지요.

구분 클러스터드 인덱스 넌클러스터드 인덱스
차이 물리적으로 행을 재배열 물리적으로 행을 재배열하지 않는다.
크기 비교적 작다. 클러스터드 인덱스보다 크다.
선택도 30% 정도면 사용한다. 3% 이내면 사용한다.
최대 갯수 테이블당 1개 테이블당 249개

다음으로 클러스터드 인덱스가 있는 테이블의 넌클러스터드 인덱스를 알아 보도록 하지요.

물론 당연히 클러스터드 인덱스와 넌 클러스터드 인덱스가 있을 때 넌클러스터드 인덱스를 조회할 경우겠지요?

현재는 번호에 클러스터드 인덱스가 걸린 상태이며, 이름에 넌클러스터드 인덱스가 설정된 상태입니다.

이런 식으로 구성이 되게 됩니다. 먼저 알아 두셔야 할 것은!!

넌클러스터드 인덱스의 RID는 더 이상 RID가 아닌 클러스터드 인덱스의 키값을 가지게 됩니다.

좀 더 간단히 실제 조회를 해 보도록 하지요. 넌클러스터드 인덱스가 걸린 이름 컬럼의 유병수라는 이름을 조회해 보도록 합시다.

박훈 < 유병수 < 이수선 이므로 넌클러스터드 중간 레벨의 2페이지로 가게 될겁니다.

여기서 유병수를 찾으니 유병수는 클러스터드 인덱스 10번 키값을 가지고 있습니다. 10이라는 값을 가지고 클러스터드 인덱스 페이지로 가니 10은 데이터페이지 4에 있다고 합니다.

데이터페이지 4로 가니? 바로 10 유병수를 찾을 수 있게 되지요.

네, 맞습니다. 바로 이런 그림이 되는 것이지요. 만약 한기환을 찾으려 한다면 어떻게 될까요?

한기환 < 한기환 이므로 넌클러스터드 중간 레벨의 4페이지로 가게 되겠죠?

클러스터드 인덱스의 키값 2이니. 1 < 2 < 4 이므로 1 데이터 페이지로 가게 되며 1 데이터 페이지에서 2번 한기환을 발견하게 될 겁니다.

어떠세요? 조금 감이 잡히시나요? ^_^ 내부적인 부분이라 조금 어렵기도 하시겠지만 중요한 부분이랍니다.

다음 장에서는 실제 색인을 여러가지 방법으로 생성하고 수행해 볼 겁니다. 수고하셨습니다.


출처 : http://www.tiptech.net/lecture/sql/sql2000/index2.html

'PP > DB' 카테고리의 다른 글

Sql injection 방어 코딩  (0) 2012.01.07
MSACCESS MDB 저장프로시저 사용하기  (0) 2012.01.07
Oracle과 MSSQL 데이터타입 비교/매치/차이/치환  (0) 2012.01.07
posted by 방랑군 2012. 1. 7. 15:41

출처 :  http://najsulman.tistory.com/591

 휴우~ 각고의 노력끝에 드뎌 성공~!!!


휠자가 하려고 했던 것은 다음과 같다.
1. ActiveX에서 마우스 클릭 시 이벤트를 ClientScript에 통지!!
2. 통지 받으면 Ajax로 서버딴에 DB질의를 요청
3. 서버쪽에서는 웹서비스로 DB에 질의 요청 후 받은 데이터를 JSON으로 변환
4. 기다리고 있던 ClientScript에서는 JSON으로 질의에 대한 응답을 받음

현재 설명하려고 하는 내용은 Ajax로 서버딴에 DB질의 요청 및 받은 데이터를 JSON으로 변환하는 것이에용

ClientScript에서 Ajax로 질의 요청 하는 Ajax구문
<script type ="text/javascript" language="javascript" for="NVS" EVENT="RcvSelectedCamera(CameraCode)">
$.ajax({
type: "post",
url: "Tmp.asmx/HelloPreset",
data: "{" + CameraCode + "}",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data){
alert('success - ' + data.d);
},
error: function(result){
alert('error - ' + result.status + ' ' + result.statusText);
}

});

</script>


JSON으로 변환
- 웹서비스쪽에서 JSON으로 변환해줌

DataSet을 JSON으로 변환해줄 클래스 정의


namespace ICSService
{
public class DataSetConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
//Define the DataTable as a supported type.
get { return new ReadOnlyCollection<Type>(new List<Type>(new Type[] { typeof(DataSet) })); }
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
Dictionary<string, object> dtDic = new Dictionary<string, object>();
DataSet ds = obj as DataSet;
foreach (DataTable dt in ds.Tables)
{
// Create the representation.
Dictionary<string, object> rowDic = new Dictionary<string, object>();
int i = 0;
foreach (DataRow row in dt.Rows)
{
//Add each entry to the dictionary.
Dictionary<string, object> colDic = new Dictionary<string, object>();
foreach (DataColumn col in row.Table.Columns)
{
colDic.Add(col.ColumnName, row[col]);
}
rowDic.Add("row" + (i++).ToString(), colDic);
}
dtDic.Add(dt.TableName, rowDic);
}
return dtDic;
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
if (type == typeof(DataTable))
{
// Create the instance to deserialize into.
DataTable list = new DataTable();
// Deserialize the ListItemCollection's items.
ArrayList itemsList = (ArrayList)dictionary["Rows"];
for (int i = 0; i < itemsList.Count; i++)
list.Rows.Add(serializer.ConvertToType<DataRow>(itemsList[i]));
return list;
}
return null;
}
}
}
DataSetConverter 클래스의 사용

[WebMethod]
public string SelectPresetByCameraCode_Web(string[] CameraCode)
{
DataSet ds = (DataSet)XmlHelper.ExcuteXml(Server.MapPath(PRESET_XML), "SelectPresetByCameraCode_Web", CameraCode);
JavaScriptSerializer jss = new JavaScriptSerializer();
DataSetConverter dsc = new DataSetConverter();
IDictionary<string, object> retVal = dsc.Serialize(ds, jss);
string result = jss.Serialize(retVal);
return result;
}


'PP > JSON' 카테고리의 다른 글

JSON 의 eval() 함수 사용의 문제  (0) 2012.01.09
JSON Text를 JSON Object로 변환하기  (0) 2012.01.09
JSON 개요 및 예제  (0) 2012.01.04
DATASET - > JSON  (1) 2012.01.04
JSON.NET  (0) 2012.01.04
posted by 방랑군 2012. 1. 7. 14:41

'PP > Oracle' 카테고리의 다른 글

오라클 .net 라이브러리  (0) 2012.01.07
[펌]오라클 함수...  (0) 2012.01.07
[펌]오라클의 사용자 함수를 파일로 생성하기  (0) 2012.01.07
윈도우 7에 오라클 11g 설치하기.  (0) 2012.01.07
posted by 방랑군 2012. 1. 7. 08:35
posted by 방랑군 2012. 1. 7. 08:28
※ Error관련 내장함수
- SQLCODE : 현재 발생한 오류에 따른 오류 코드를 반환
- SQLERRM : 오라클 오류 코드와 연결된 오류 메시지를 반환


※ 문자열 함수
① ASCII <--> CHAR : ASCII, CHAR로 변환하기

② CONCAT : 조합하기(||와 같은 역할)
 
③ SUBSTR : 자르기(글자기준)
 
④ SUBSTRB : 자르기(바이트 기준)

⑤ INITCAP : 첫글자만 대문자, 나머지글자는 소문자로 변환하기

⑥ UPPER / LOWER : 대문자/소문자로 변환하기

⑦ LPAD / RPAD : 왼쪽채우기/오른쪽채우기

⑧ LENGTH : 문자열의 길이 반환하기

⑨ LANGUAGE : KOREAN_LOREA.KO16KSC5601/AMERICAN_AMERICA.US7ASCII

⑩ REPLACE : 문자 대체하기

⑪ INSTR : 문자열에서 해당문자의 위치 반환하기

⑫ LTRIM / RTRIM : 문자열의 왼쪽/오른쪽 공백 버리기

⑬ TRANSLATE : 문자 대체하기(REPLACE와 같은 기능이나 스트링단위가 아닌 문자단위)


※ 수학 함수
① ROUND : 반올림(해당자리수까지 보여주면서 반올림)

② TRUNC : 버림값

③ MOD : 나눈후 나머지

④ CEIL : 무조건 올림

⑤ POWER : 승수값

⑥ GREATEST : 주어진 데이터중 최대값

⑦ LEAST : 주어진 데이터중 최소값


※ DATE 함수
- ADD_MONTHS : 지정된 날짜에 1달을 더함. 만일 결과가 나온 달이 현재 일수보다 
  작은 일수를 갖고 있는 달로 변경되면 그 달의 마지막 날을 반환
- LAST_DAY : 주어진 달의 마지막 날을 반환
- MONTHS_BETWEEN : 두 날짜 사이의 개월수를 계산. 만일 두 날짜가 그 달의 마지막
  이라면 정수를 반환하고 그렇지 않으면 한달을 31로 계산한 분수값을 반환
- NEW_TIME : 사용자가 지정한 시간대에 대한 시간/날짜 값을 반환
- NEXT_DAY : 시작 날짜 다음에 지정된 요일이 처음으로 나오는 날짜를 반환
- ROUND : 월,년도,세기 등과 같이 선택한 날짜 파라미터를 반올림
- SYSDATE : 시스템 날짜와 시간을 DATE형식으로 반환
- TRUNC : 일,월 등과 같이 지정된 날짜 파라미터를 잘라냄
- date + number : date에 number만큼 후의 날짜를 보여줌(일수를 더함)
- date - number : date에 number만큼 전의 날짜를 보여줌(일수를 뺌)
- date1 - date2 : date1에서 date2까지의 총 일수를 보여줌(어떤날짜에서 다른날짜를 뺌)
- date1 + 숫자/24 : date1에서 시간을 더해 날짜를 보여줌(시간에 날짜를 더함)

① MONTHS_BETWEEN : 날짜와 날짜 사이의 개월수를 반환

② ADD_MONTHS : 날짜에 개월수를 더한 일자를 반환

③ NEXT_DAY : 해당일 다음에 오는 특정 요일을 반환

④ LAST_DAY : 지정한 달의 마지막날 반환

⑤ SYSTEM시간


※ 변환 함수
① TO_CHAR : DATE형, NUMBER형을 문자형으로 변환
② TO_NUMBER : 문자를 숫자형으로 변환
③ TO_DATE : 날자 형태의 문자열을 format에 맞게 날짜 형식으로 변환
④ NUMBER와 DATE를 문자타입으로 변환
⑤ TO_TIMESTAMP : 문자열을 timestamp형식으로 변환
⑥ NVL : null일때 0을 보여줌
⑦ DECODE : default 반환, 디폴트가 없는 경우에는 null값을 반환. 반환하는 값은 최초의
    result와 같은 데이터타입(if..then..else기능을 구사하는 유용한 함수)
⑧ NULLIF : 결과값이 동일하면 null, 그렇지 않으면 첫번째 인자값 반환
⑨ NVL2 : 첫번째 인자값이 null이 아니면 두번째 인자값, null이면 세번째 인자값 반환

* 오라클의 환경변수 값 구하기
   select userenv('language') "lanugage",userenv('sessionid') "sessionid" 

   from dual;

※ 그룹 함수
① COUNT : 행의 개수를 구함
② AVG : 평균을 구함
③ SUM : 합계를 구함
④ MIN : 최소값을 구함
⑤ MAX : 최대값을 구함
⑥ STDDEV : 표준편차를 구함
⑦ VARIALCE : 분산을 구함
⑧ VSIZE : 어떤값의 바이트수를 구함

 



posted by 방랑군 2012. 1. 7. 08:27

오라클의 사용자 함수는 생성한 사람의 노하우가 담겨있는 귀중한 소스라 할 수 있다.

 

그 중요한 소스를 카피하기 위한 방법이다.

 

오라클 프롬포트 상에서 'ED' 명령어로 파일을 하나 생성한다

 

새로 생겨난 메모장에 다음의 내용을 입력한다

 

 

SET HEADING OFF
SET FEEDBACK OFF
SPOOL 새로운파일명.TXT
SELECT 'CREATE' FROM DUAL
UNION ALL
SELECT TEXT
FROM USER_SOURCE
WHERE NAME = '함수명';
SPOOL OFF
SET HEADING ON
SET FEEDBACK ON

 

 

입력후 저장하면 새로운 파일명.TXT 에 소스가 그대로 있다.

 

그걸 그대로 실행하면 새로운 환경에서 똑같은 함수를 생성할 수 있다.



출처 : [출처] 오라클의 사용자 함수를 파일로 생성하기|작성자 세상에홀로서기

'PP > Oracle' 카테고리의 다른 글

WINDOWS SERVER 2008 에 ORACLE 11G 설치  (0) 2012.01.07
오라클 .net 라이브러리  (0) 2012.01.07
[펌]오라클 함수...  (0) 2012.01.07
윈도우 7에 오라클 11g 설치하기.  (0) 2012.01.07
posted by 방랑군 2012. 1. 7. 08:25

출처 : 
http://liveislim.tistory.com/29 

아후 매번 귀찮아서 모를때마다 검색해서 찾아보고 했었는데... 안되겠다 싶어서 내 공간에 정리 해볼려 한다.


오라클 11g가 xp용으로 나온다 그래서 윈도우7에 설치하려면 몇 가지 설정을 해야 한다.....

우선 오라클 사이트로 이동해서 오라클을 다운로드 한다. ==> www.oracle.com 

참고로 전 Oracle Database 11g Release 2 Microsoft Windows(32-bit) 다운 로드 하였습니다.

자 이제 다운로드가 완료되면 압축을 풉니다...(흑 설치하면서 글도 같이 쓰니 아 구구구 귀찮아...)

1. database폴더로 이동하면 setup.exe 파일이 있을 것입니다. 파일을 선택하고 마우스 오른쪽을 클릭하여 속성창을 여세요!

아래 화면과 같이 호환성 탭을 선택한 후 호환모드를 아래와 같이 선택 하여 주신 후 확인 버튼을 클릭합니다.


2. 유동아이피 환경설정 인데요..이것은 오라클이 DHCP할당 방식 IP주소를 사용하는 시스템에서 설치를 지원하기 위해서 한

다는 것 같은데 솔직히 잘 모르겠습니다. 잘 따라하면 어렵지 않습니다.

우선 시작 -> 실행 -> hdwwiz 입력한 후 확인을 클립합니다. (혹시 실행이라는 메뉴가 안보이실 때는 작업표시줄에서 

마우스 오른쪽을 클릭 -> 속성 -> 시작메뉴 -> 사용자지정 -> 실행 이라는 항목을 체크 하시고 적용을 누르시면 됩니다)


하드웨어 추가마법사 창이 화면에 나오면 다음을 클릭합니다. 


아래 화면과 같이 목록에서 직접 선택한 하드웨어 설치(고급)이라는 라디오 박스를 클릭 합니다.


추가할 하드웨어 종류를 선택하는 화면이 나오는데 여기에서 네트워크 어댑터를 선택 한 후 다음을 클릭합니다.


네트워크 업댑터 선택하는 화면이 나오는 데요 아래의 화면과 같이 제조사를 "Microsoft"  

네트워크 어덥터를 "Microsoft Loopback Adapter" 를 선택 하고 다음을 누릅니다. 또다시  다음을 선택하면 해당 하드웨어가
 
설치되었다는 화면을 만날 수 있습니다.



이제 설치된 어탭터에 아이피를 설정해 주어야 합니다. 일단 아이피 설정을 하기 위해서 제어판 -> 네트워크 및 인터넷 -> 

네트워크 및 공유센터 -> 어댑터 설정변경을 선택 합니다. 


어댑터 선택 하면이 나오면 위에서 추가한 Microsoft Loopback Adapter 선택하고 마우스 오른쪽 클릭 후 속성창을 띄웁니다.


속성창에서 Internet Protocol Version 4(Tcp/ipv4) 를 선택 한 후 속성버튼을 클릭 합니다.


속성창이 나오면 아래 화면과 같이 아이피를 수정한 후 확인 버튼을 클릭 합니다. 아마 세그 먼트 뭐시기뭐시기 나오는데

무시하고 진행하시면 됩니다.


이제 해당 네트워크 config만 설정해주면 끝입니다. 일단 수정해줘야 할 파일의 

위치는 C:\Windows\System32\drivers\etc  hosts라는 파일 입니다.  해당 파일을 노트페트 같은 메모장으로 열으시면 

됩니다. 가령 권한 관련하여 열수 없다고 나오면 메모장 아이콘을 클릭한 후 오른쪽 버튼을 클릭하고 관리자 권한으로 실행를 

클릭한 후 해당 파일을 열어서 사용하시면 됩니다...

내용은 아래 화면과 같이 아까 설정한 ip번호와 해당 pc이름을 입력하여 주면 됩니다.


이제 설치를 위한 과정은 모두 끝이 났습니다.. 이제 부터 설치를 하시면 됩니다.. 

와 정말 이지 화면 떠가면서 이런 글을 올리시는 분들은 정말 존경할 수 밖에 없을것 같습니다.. 시간도 시간이지만 정성이

아마 저는 다시는 이짓을 못하지 않을까 합니다... 

'PP > Oracle' 카테고리의 다른 글

WINDOWS SERVER 2008 에 ORACLE 11G 설치  (0) 2012.01.07
오라클 .net 라이브러리  (0) 2012.01.07
[펌]오라클 함수...  (0) 2012.01.07
[펌]오라클의 사용자 함수를 파일로 생성하기  (0) 2012.01.07
posted by 방랑군 2012. 1. 7. 00:52

'PP > Node.js' 카테고리의 다른 글

node.js 개발하기 STEP 0. 준비  (0) 2012.01.05
node.js를 서비스에 활용하는 회사들.  (0) 2012.01.05
posted by 방랑군 2012. 1. 6. 23:36
1. Uploadify.htm
<head>
    <title>파일업로드 : jQuery + Uploadify + ASP.NET</title>
    <link href="uploadify.css" rel="stylesheet" type="text/css" />
    
    <script type="text/ecmascript" src="jquery-1.4.2.min.js"></script>
    <script src="jquery.uploadify.v2.1.4.js" type="text/javascript"></script>
    <script src="swfobject.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            // Uploadify 파일 업로드 컨트롤 : Flash가 설치가 되어있어야 함
            $('#fileInput').uploadify({
                'uploader': 'uploadify.swf', // Uploadify 컨트롤 지정
                'script': 'Uploadify.ashx', // 서버측 스크립트, ASP.NET, ASP, PHP, JSP
                'cancelImg': 'cancel.png', // 취소 이미지
                'auto': false, // true면 파일선택시 바로 자동으로 업로드됨
                'folder': '/Uploads', // 업로드할 폴더 : 가상디렉터리 + 업로드폴더
                // 업로드 완료시 처리 :
                //      주요 속성은 http://www.uploadify.com/documentation/ 참고
                'onComplete': function (event, queueID, fileObj, response, data) {
                    $('#lblFile').append('<a href=/WebJQuery' + fileObj.filePath + '>'
                    + fileObj.name + '</a><br>');
                }
            });
            // 버튼 클릭시 업로드
            $('#btn').click(function () { $('#fileInput').uploadifyUpload(); });
        });
    </script>
</head>
<body>
    <input id="fileInput" name="fileInput" type="file" />
    <input type="button" id="btn" value="업로드" />
    <div id="lblFile"></div>
</body>
</html>

2. Uploadify.ashx
<%@ WebHandler Language="C#" Class="Uploadify" %>
 
using System;
using System.Web;
 
public class Uploadify : IHttpHandler {
   
    public void ProcessRequest (HttpContext context) {
        // Filedata로 넘겨온 파일 값 받기
        HttpPostedFile file = context.Request.Files["Filedata"];
        // 저장할 폴더
        string targetDirectory = System.IO.Path.Combine(
        context.Request.PhysicalApplicationPath,
        context.Request["folder"].Replace("/", ""));
        // 저장할 폴더 + 파일명
        string targetFilePath = System.IO.Path.Combine(
            targetDirectory, file.FileName);
        // 파일 저장(업로드)
        file.SaveAs(targetFilePath);
 
        context.Response.Write("RedPlus");
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }
 

'PP > Upload' 카테고리의 다른 글

실시간 파일 업로드 - uploadify  (0) 2012.01.04
posted by 방랑군 2012. 1. 6. 23:22

출처 : http://infosearchshop.com/Content.aspx?id=7vWHuJea+Lw=&title=Making+thumbnail+dynamically+with+ashx+file+in+asp.net

 

In this article I am going to show how to resize image dynamically or making thumbnail dynamically with ashx file.Start new website project give name thumbnail.In menu go to Webite > Add new item and select Generic Handler. Name it Handler.ashx, You will get auto generated code in it like given below:

<%@ WebHandler Language="C#" Class="Handler" %>

using System;
using System.Web;

public class Handler : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "text/plain";
        context.Response.Write("Hello World");
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }

}


Now add given namespace to handle the image files
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

 

Make a new folder for images files, name it images. Put some images in this folder.

Now our next step is getting the height , width , image name and changing image size.
 To do these things, here query string is used. In ProcessRequest method write follwing lines.

 

public class Handler : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
 // for new height of image
  int h=int.Parse(context.Request.QueryString["h"].ToString()); 
 // for new width of image
        int w = int.Parse(context.Request.QueryString["w"].ToString());
         // for  image file name
        string file = context.Request.QueryString["file"].ToString();

 // Path of image folder where images files are placed
 string  filePath = context.Server.MapPath("~/images/" + file);

 // Resize proccess
   using(System.Drawing.Image img=System.Drawing.Image.FromFile(filePath))
    {
       Bitmap objBmp = new Bitmap(img,w, h);
        string extension = Path.GetExtension(filePath);
        MemoryStream ms; 
        byte[] bmpBytes;
        switch (extension.ToLower())
        {
            case ".jpg":
            case ".jpeg": 
                ms = new MemoryStream();
                objBmp.Save(ms, ImageFormat.Jpeg);
                bmpBytes = ms.GetBuffer();
                context.Response.ContentType = "image/jpeg";
                context.Response.BinaryWrite(bmpBytes);
                objBmp.Dispose();
                ms.Close();
                context.Response.End();
                break;
            case ".png":
                  ms = new MemoryStream();
                  objBmp.Save(ms, ImageFormat.Png);
                  bmpBytes = ms.GetBuffer();
                 context.Response.ContentType = "image/png";
                 context.Response.BinaryWrite(bmpBytes);
                 objBmp.Dispose();
                 ms.Close();
                 context.Response.End();
            break;
           case ".gif":
                ms = new MemoryStream();
                objBmp.Save(ms, ImageFormat.Gif);
                bmpBytes = ms.GetBuffer();
                context.Response.ContentType = "image/png";
                context.Response.BinaryWrite(bmpBytes);
                objBmp.Dispose();
                ms.Close();
                context.Response.End();
                break;
  
        }
        img.Dispose();
   }

    }

 

Now we move to Default.aspx page, drag here  Image tool from tool box :

    <asp:Image ID="img1" runat="server" /><br />
For retriving the image set ImageUrl as given below with height width and image name.

<asp:Image ID="img1" runat="server" ImageUrl="~/Handler.ashx?h=50&w=50&file=Winter.jpg" /><br />

And now finally run the default.aspx and see the result.

posted by 방랑군 2012. 1. 6. 23:21

출처 : http://www.west-wind.com/weblog/posts/283.aspx

 

 

One frequent task is to take images and convert them into thumbnails. This is certainly nothing new, but seeing this question is so frequently asked on newsgroups and message boards bears reviewing this topic here again.

 

I was getting tired of constantly repeating this code for specific situations, so I created a generic page in my apps to handle resizing images from the current site dynamically in a page called CreateThumbnail. You call this page with a relative image name from the Web site on the querystring and it returns the image as a thumbnail.

 

An example of how this might work looks like this:

 

http://www.west-wind.com/wwStore/demos/CreateThumbnail.aspx?image=images/WebStoreLogo_big.jpg&size=400

 

Size is an optional second parameter – it defaults to 120.

 

Here’s what the implementation of this generic page looks like:

 

using System.Drawing;

using System.Drawing.Imaging;

 

public class CreateThumbNail : System.Web.UI.Page

{

private void Page_Load(object sender, System.EventArgs e)

      {

            string Image = Request.QueryString["Image"];

            if (Image == null

            {

                  this.ErrorResult();

                  return;

            }

 

            string sSize = Request["Size"];

            int Size = 120;

            if (sSize != null)

                  Size = Int32.Parse(sSize);

 

            string Path = Server.MapPath(Request.ApplicationPath) + "\\" + Image;

            Bitmap bmp = CreateThumbnail(Path,Size,Size);

 

            if (bmp == null)

            {

                  this.ErrorResult();

                  return;

            }

 

            string OutputFilename = null;

            OutputFilename = Request.QueryString["OutputFilename"];

 

            if (OutputFilename != null)

            {

                  if (this.User.Identity.Name == ""

                  {

                        // *** Custom error display here

                        bmp.Dispose();

                        this.ErrorResult();

                  }

                  try

                  {

                        bmp.Save(OutputFilename);

                  }

                  catch(Exception ex)

                  {

                        bmp.Dispose();

                        this.ErrorResult();

                        return;

                  }

            }

 

            // Put user code to initialize the page here

            Response.ContentType = "image/jpeg";

            bmp.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Jpeg);

            bmp.Dispose();

      }

 

      private void ErrorResult()

      {

            Response.Clear();

            Response.StatusCode = 404;

            Response.End();

      }

 

      ///

      /// Creates a resized bitmap from an existing image on disk.

      /// Call Dispose on the returned Bitmap object

      ///

      ///

      ///

      ///

      /// Bitmap or null

      public static Bitmap CreateThumbnail(string lcFilename,int lnWidth, int lnHeight)

      {

     

            System.Drawing.Bitmap bmpOut = null;

            try

            {

                  Bitmap loBMP = new Bitmap(lcFilename);

                  ImageFormat loFormat = loBMP.RawFormat;

 

                  decimal lnRatio;

                  int lnNewWidth = 0;

                  int lnNewHeight = 0;

 

                  //*** If the image is smaller than a thumbnail just return it

                  if (loBMP.Width < lnWidth && loBMP.Height < lnHeight)

                        return loBMP;

           

 

                  if (loBMP.Width > loBMP.Height)

                  {

                        lnRatio = (decimal) lnWidth / loBMP.Width;

                        lnNewWidth = lnWidth;

                        decimal lnTemp = loBMP.Height * lnRatio;

                        lnNewHeight = (int)lnTemp;

                  }

                  else

                  {

                        lnRatio = (decimal) lnHeight / loBMP.Height;

                        lnNewHeight = lnHeight;

                        decimal lnTemp = loBMP.Width * lnRatio;

                        lnNewWidth = (int) lnTemp;

                  }

 

                  // System.Drawing.Image imgOut =

                  //      loBMP.GetThumbnailImage(lnNewWidth,lnNewHeight,

                  //                              null,IntPtr.Zero);

                 

                  // *** This code creates cleaner (though bigger) thumbnails and properly

                  // *** and handles GIF files better by generating a white background for

                  // *** transparent images (as opposed to black)

                  bmpOut = new Bitmap(lnNewWidth, lnNewHeight);

                  Graphics g = Graphics.FromImage(bmpOut);

                  g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

                  g.FillRectangle( Brushes.White,0,0,lnNewWidth,lnNewHeight);

                  g.DrawImage(loBMP,0,0,lnNewWidth,lnNewHeight);

 

                  loBMP.Dispose();

            }

            catch

            {

                  return null;

            }

     

            return bmpOut;

      }

 

}

 

This code doesn’t use the CreateThumbnail method of GDI+ because it doesn’t properly convert transparent GIF images as it draws the background color black. The code above compensates for this by first drawing the canvas white then loading the GIF image on top of it. Transparency is lost – unfortunately GDI+ does not handle transparency automatically and keeping Transparency intact requires manipulating the palette of the image which is beyond this demonstration.

 

The Bitmap object is returned as the result. You can choose what to do with this object. In this example it’s directly streamed in the ASP. Net Output stream by default. If you specify another query string value of OutputFilename you can also force the file to be written to disk *if* you are logged in. This is definitely not something that you want to allow just ANY user access to as anything that writes to disk is potentially dangerous in terms of overloading your disk space. Writing files out in this fashion also requires that the ASPNET or NETWORK SERVICE or whatever account the ASP. Net app runs under has rights to write the file in the specified directory. I’ve provided this here as an example, but it’s probably best to stick file output functionality into some other more isolated component or page that is more secure.

 

Notice also that all errors return a 404 file not found error. This is so that images act on failure just as if an image file is not available which gives the browser an X’d out image to display. Realistically this doesn’t matter – browsers display the X anyway even if you send back an HTML error message, but this is the expected response the browser would expect.

 

In my West Wind Web Store I have several admin routines that allow to resize images on the fly and display them in a preview window. It’s nice to preview them before writing them out to disk optionally. You can also do this live in an application *if* the number of images isn’t very large and you’re not pushing your server to its limits already. Image creation on the fly is always slower than static images on disk. However, ASP. Net can be pretty damn efficient using Caching and this scenario is made for it. You can specify:

<%@ OutputCache duration="10000" varybyparam="Image;Size" %>

 

in the ASPX page to force images to cache once they’ve been generated. This will work well, but keep in mind that bitmap images can be memory intensive and caching them can add up quickly especially if you have large numbers of them.

 

If you create images dynamically frequently you might also consider using an HTTP Handler to perform this task since raw Handlers have less overhead than the ASP.Net Page handler. For example, the Whidbey Dynamic Image control relies on an internal handler that provides image presentation 'dynamically' without having to save files to disk first.

posted by 방랑군 2012. 1. 6. 23:21

출처 : http://ryunad.tistory.com/tag/C%23%20%EC%9D%B4%EB%AF%B8%EC%A7%80%20%EC%8D%B8%EB%84%A4%EC%9D%BC

 

 

간단하게 이미지를 하나 선택하면 선택한 이미지의 Thumbnail을 만드는 로직입니다.

윈 폼으로 만들었지만 로직부분만 재활용하면 ASP.NET이든 WPF든 어디서든 사용이 가능합니다.

 

 

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Runtime.Serialization.Formatters.Binary;

using System.IO;

namespace Ex11 

    public partial class MainForm : Form 
    { 
        private Person _person = new Person();

        public MainForm() 
        { 
            InitializeComponent(); 
        }

        private void btnLoadPicture_Click(object sender, EventArgs e) 
        { 
            //1. 파일 불러오기 
            OpenFileDialog dlg = new OpenFileDialog(); 
            if (DialogResult.OK == dlg.ShowDialog()) 
            { 
                string path = Application.StartupPath;

                string fileName = 
                    dlg.FileName.Substring( 
                    dlg.FileName.LastIndexOf("\\") + 1); 
                string filePath = 
                    Path.Combine(path, fileName); 
                int dotPosition = fileName.LastIndexOf("."); 
                string thumbnailName = 
                    fileName.Substring(0, dotPosition) + 
                    "_small" + 
                    fileName.Substring(dotPosition); 
                string thumbnailPath = 
                    Path.Combine(path, thumbnailName); 
                if (File.Exists(filePath)) 
                    File.Delete(filePath); 
                //2. 원본이미지 복사 및 thumbnail 이미지 생성 
                File.Copy(dlg.FileName, filePath); 
                Image image = 
                    Image.FromFile(filePath); 
                Image thumbnail = 
                    image.GetThumbnailImage(150, 150, null, IntPtr.Zero); 
                //picture 이미지 해제 
                if (pbPicture.Image != null) 
                { 
                    pbPicture.Image.Dispose(); 
                } 
                if (File.Exists(thumbnailPath)) 
                    File.Delete(thumbnailPath); 
                thumbnail.Save(thumbnailPath);

                //이미지 객체의 해제 
                image.Dispose(); 
                thumbnail.Dispose(); 
                //3. 이미지 표시 
                pbPicture.Image = 
                    Image.FromFile(thumbnailPath);

                _person.ImagePath = fileName; 
            } 
        }

        private void miSave_Click(object sender, EventArgs e) 
        { 
            _person.Name = txtName.Text; 
            _person.ResidentNumbers = txtResidentNumber.Text; 
            _person.BirthDate = DateTime.Parse(txtBirthDate.Text); 
            _person.Height = int.Parse(txtHeight.Text); 
            _person.Weight = int.Parse(txtWeight.Text); 
            _person.Phone = txtPhone.Text; 
            _person.Email = txtEmail.Text;

            string path = Path.Combine(Application.StartupPath, "person.dat"); ; 
            FileStream stream = new FileStream(path, FileMode.Create); 
            BinaryFormatter formatter = new BinaryFormatter(); 
            formatter.Serialize(stream, _person); 
            stream.Close();

            MessageBox.Show("저장되었습니다."); 
        }

        private void miOpen_Click(object sender, EventArgs e) 
        { 
        }

        private void MainForm_Load(object sender, EventArgs e) 
        { 
            string path = Path.Combine(Application.StartupPath,"person.dat"); 
            if (File.Exists(path)) 
            { 
                FileStream stream = new FileStream(path, FileMode.Open); 
                BinaryFormatter formatter = new BinaryFormatter(); 
                _person = (Person)formatter.Deserialize(stream); 
                txtName.Text = _person.Name; 
                txtResidentNumber.Text = _person.ResidentNumbers; 
                txtBirthDate.Text = _person.BirthDate.ToString("yyyy-MM-dd"); 
                txtHeight.Text = _person.Height.ToString(); 
                txtWeight.Text = _person.Weight.ToString(); 
                txtPhone.Text = _person.Phone; 
                txtEmail.Text = _person.Email;

                string fileName = _person.ImagePath; 
                fileName = fileName.Insert(fileName.LastIndexOf("."), "_small"); 
                string imagePath = Path.Combine(Application.StartupPath, fileName); 
                if (File.Exists(imagePath)) 
                { 
                    pbPicture.Image = Image.FromFile(imagePath); 
                } 
            } 
        } 
    } 
}

[출처] C# 이미지 섬네일|작성자 괴무리

'PP > ASP.NET' 카테고리의 다른 글

[asp.net] ashx 이미지 섬네일  (0) 2012.01.06
[asp.net] 이미지 섬네일  (0) 2012.01.06
[.ASHX 파일]jQuery 제너릭 처리기(ashx)로 DB/데이터배이스 받기/사용 핸들러/handler  (0) 2012.01.06
GENERIC  (0) 2012.01.04
Generic  (0) 2012.01.04
posted by 방랑군 2012. 1. 6. 23:20
출처 :   http://blog.yahoo.com/_SPX445PUEEEIIXT52JGVCSUPBQ/articles/503589 

Handler를 이용한 방법은 제가 자세한 원리는 잘 모르기 때문에 사용예제만 하나 올리겠습니다.

aspx페이지를 안만들고 ashx를 만들면 성능상 더 좋다고 합니다.

우선 ashx파일을 만듭니다.



넵 만들고 나면 기본적으로 이런코드만 나옵니다.
여기서 우선 알아두셔야할게 빨강 네모에 이 ashx파일이 내놓는 자료형식을 코드해주셔야 합니다.
저는 JSON형식을 사용하기 때문에 text/json으로 코드하겠습니다.
초록색 네모부분에는 출력할 결과문이 들어갈 자리입니다.



그런데 기본코드에서 빠진부분이 있습니다. 밑에 그림처럼 인코딩형식을 UTF8로 맞춰저야 합니다.
밑에 초록색은 안넣으셔도 상관없지만 보안상 넣어주시는게 좋다고 합니다.(정확히는 저도 잘 ^^;;)
여기까지가 밑준비 입니다.
원본 크기의 사진을 보려면 클릭하세요

이제 위쪽에 우리가 정말로 알고싶은 정보를 받아와서 JSON형식으로 바꿔주시면 됩니다.
그리고 다 바꾸고 나서는 꼭 Write메서드의 괄호안을 바꿔줍시다.
저는 다 알맞게 해놓고, 그부분을 빼먹어서 계속 Hello World가 나오더군요;;

원본 크기의 사진을 보려면 클릭하세요


넵 이걸로 ashx는 끝났습니다. 이제 받아서 사용하시기만 하면 됩니다.
jQuery에서 받아서 사용하는 방법은 예전에 올린 호스팅이랑 똑같습니다. 물론 불러올 페이지는 전에 aspx에서
이번에 만든 ashx파일경로로 바꿔주셔야 하죠 ^^


 

'PP > ASP.NET' 카테고리의 다른 글

[asp.net] ashx 이미지 섬네일  (0) 2012.01.06
[asp.net] 이미지 섬네일  (0) 2012.01.06
C# 이미지 섬네일  (0) 2012.01.06
GENERIC  (0) 2012.01.04
Generic  (0) 2012.01.04
posted by 방랑군 2012. 1. 6. 23:02


System.IO.FileStream
System.IO.MemoryStream
System.IO.BufferedStream
System.Net,Sockets.NetworkStream
System.Security,Cryptography.CryptoStream : 암호화 객체를 스트림으로 다룬다.