본문 바로가기
Borland

HOWTO: 파일을 Internet Information Server에 업로드하는 방법

by leo21c 2008. 1. 17.
SMALL

HOWTO: 파일을 Internet Information Server에 업로드하는 방법

기술 자료 ID:184352
마지막 검토:2005년 8월 24일 수요일
수정:4.1
이 문서는 이전에 다음 ID로 출판되었음: KR184352

요약

프로그램 방식으로 클라이언트 응용 프로그램에서 Internet Information Server(IIS)에 파일을 업로드하는 데 사용할 수 있는 여러 가지 방법이 있습니다. 본 문서에서는 그러한 방법 중 일부를 제공하고 HTTP PUT 기능을 적용하는 방법을 설명합니다.

위로 가기

추가 정보

WebPost API 사용

파일을 업로드하는 한 가지 방법은 HTTP POST 메서드나 ActiveX 업로드 컨트롤과 함께 WebPost API를 사용하는 것입니다. WebPost API에 대해서는 Internet Client SDK에 자세히 설명되어 있습니다.

이 경우 두 방법 모두에서 게시된 데이터를 처리하고 서버의 파일 시스템에서 파일에 그 데이터를 저장하는 특수한 구성 요소가 서버에 있어야 한다는 단점이 있습니다. FTP 게시 공급자를 사용할 때의 WebPost 및 ActiveX 컨트롤 업로드는 예외입니다. 그러나, 이 경우에는 WWW 서버와 더불어 FTP 서버를 설치하고 구성해야 합니다.

Windows NT 4.0 옵션 팩(NTOP)에 포함된 Microsoft Posting Acceptor는 위에서 설명한 방법을 통해 파일 업로드를 위한 백 엔드(Back End) 기능을 제공합니다. Posting Acceptor와 파일 업로드 컨트롤의 구성 및 사용 방법에 대한 자세한 내용은 NTOP에 제공된 NTOP 설명서와 Microsoft Posting Acceptor 릴리스 정보를 참조하십시오.

위로 가기

HTTP 프로토콜 PUT 기능 사용

HTTP 프로토콜 PUT 기능을 이용한 방법에서는 서버에서 업로드 데이터를 처리하기 위한 구성 요소가 필요 없습니다. PUT 기능은 IIS 4.0에 기본으로 제공됩니다. 모든 인터넷 브라우저가 HTTP PUT 동사(Verb)를 처리할 수 있는 것은 아닙니다. 아래의 내용은 WinInet API를 사용하여 작성한 응용 프로그램에 적용됩니다. 프로그래머는 이 API를 이용하여 프로그램 방식으로 HTTP 요청을 만들어 전송할 수 있습니다.

PUT 메서드에 대해서는 다음 위치에 있는 HTTP/1.1 RFC 2068에 설명되어 있습니다. http://www.w3c.org/Protocols/rfc2068/rfc2068 (http://www.w3c.org/Protocols/rfc2068/rfc2068)

클라이언트는 이 메서드를 사용하여 URL을 제공하고 요청의 본문(body)에서 데이터를 전송합니다. POST와 PUT의 주된 차이점은 PUT의 경우 URL은 클라이언트의 데이터를 처리할 서버 응용 프로그램의 이름이 아닙니다. 이 때의 URL은 받은 데이터를 저장하기 위해 서버가 만들 파일의 이름입니다. URL이 이미 있으면 서버가 그것을 덮어씁니다. URL에서 참조되는 가상 디렉터리에는 쓰기 사용 권한이 설정되어야 합니다. IIS 4.0의 경우 MMC에서 디렉터리 등록 정보를 통해 이 사용 권한을 구성할 수 있습니다.

예를 들어, 동사(Verb)와 URL만 보이는 아래의 HTTP 요청은 /test 가상 디렉터리에 Page.htm 파일을 만듭니다. 이 파일에는 요청과 함께 전송된 데이터가 포함됩니다.
   PUT /Test/Page.htm

프로그래머는 WinInet API를 이용하여 유효한 어떤 HTTP 요청이나 만들 수 있기 때문에 데이터를 서버에 업로드하기 위해 쉽게 이 API를 사용할 수 있습니다. 아래의 단계를 수행해야 합니다.
1.PUT 동사(Verb)를 사용하여 요청을 열어야 합니다.
2.요청할 당시 파일이 있어야 하는 것은 아니지만 요청의 개체는 NULL이 아닐 수도 있고 서버에서 유효한 URL이어야 합니다.
3.새로 생성된 URL은 요청과 함께 제공된 데이터를 포함합니다.
아래는 사용할 수 있는 예제 코드의 일부입니다.
   ...   hReq = HttpOpenRequest (hConnect, "PUT", "/test/page.htm", ...)   CHAR szContent [] = "Hello, World!"   HttpSendRequest (hReq, NULL, 0, szContent, lstrlen (szContent))   ...

이 코드를 실행할 때 IIS 4.0은 /test 가상 디렉터리에 Page.htm 파일을 만듭니다. 이 파일은 "Hello, World!"라는 문자열을 포함합니다.

HttpSendRequest는 제한된 크기의 단일 버퍼에만 사용할 수 있습니다. HttpSendRequestEx와 InternetWriteFile은 아래와 같이 크기에 관계없이 버퍼를 전송하는 데 사용할 수 있습니다.
BOOL UseHttpSendReqEx(HINTERNET hConnect, TCHAR *upFile)   {     INTERNET_BUFFERS BufferIn = {0};     DWORD dwBytesRead;     DWORD dwBytesWritten;     BYTE pBuffer[1024]; // Read from file in 1K chunks     BOOL bRead, bRet;     BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS );     HINTERNET hRequest = HttpOpenRequest (hConnect, "PUT",         "/test/page.htm", NULL, NULL, NULL,  0, 0);     if (!hRequest)     {       printf("Failed to open request handle: %lu\n", GetLastError ());       return FALSE;     }     HANDLE hFile = CreateFile (upFile, GENERIC_READ, FILE_SHARE_READ,         NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);     if (hFile == INVALID_HANDLE_VALUE)     {       printf("\nFailed to open local file %s.", upFile);       return FALSE;     }     BufferIn.dwBufferTotal = GetFileSize (hFile, NULL);     printf ("File size is %d\n", BufferIn.dwBufferTotal );     if(!HttpSendRequestEx( hRequest, &BufferIn, NULL, HSR_INITIATE, 0))     {       printf( "Error on HttpSendRequestEx %lu\n",GetLastError() );       return FALSE;     }     DWORD sum = 0;     do     {       if  (!(bRead = ReadFile (hFile, pBuffer, sizeof(pBuffer),           &dwBytesRead, NULL)))       {         printf ("\nReadFile failed on buffer %lu.",GetLastError());         break;       }       if (!(bRet=InternetWriteFile( hRequest, pBuffer, dwBytesRead,           &dwBytesWritten)))       {         printf ("\nInternetWriteFile failed %lu", GetLastError());         break;       }       sum += dwBytesWritten;     }     while (dwBytesRead == sizeof(pBuffer)) ;     CloseHandle (hFile);     printf ("Actual written bytes: %d\n", sum);     if(!HttpEndRequest(hRequest, NULL, 0, 0))     {       printf( "Error on HttpEndRequest %lu \n", GetLastError());       return FALSE;     }     return TRUE;   }

참고: IIS는 GET 요청을 처리한 후 곧바로 파일을 잠글 수도 있습니다. 따라서, 아래와 같이 연속된 요청에서 두 번째 PUT은 실패할 수도 있습니다.
   PUT /page.test   GET /page.test   PUT /page.test

잠금 위반으로 인해 오류가 발생했더라도 IIS는 리소스에서 ACL로 인해 발생한 오류(오류 401.3)라고 보고할 수도 있습니다. 아래와 같은 방법으로 이 문제를 해결할 수 있습니다.
두 번째 요청이 실패하면 기다렸다가 나중에 다시 요청을 시도합니다. IIS가 파일의 잠금을 해제하는 데 필요한 시간은 일정하지 않을 수도 있습니다.
PUT 메서드를 사용하여 다른 이름으로 파일을 URL에 넣습니다.
많이 사용되는 방법으로, HTTP의 DELETE 메서드를 사용하여 파일을 삭제한 다음 PUT을 사용하여 다시 넣습니다. 본 문서의 시작 부분에서 언급한 HTTP RFC에서 DELETE 메서드에 대한 자세한 내용을 볼 수 있습니다. 아래의 코드는 DELETE 요청을 만드는 방법을 보여줍니다.
HttpOpenRequest (hConnect,                        "DELETE",  // HTTP Verb                        "/page.test",   // Object                        ...)

위로 가기

참조

자세한 내용은 아래의 문서 번호를 눌러 Microsoft 기술 자료에 있는 문서를 참고하십시오.
177188 (http://support.microsoft.com/kb/177188/KO/)POST로 많은 양의 데이터를 요청할 때 HttpSendRequestEx를 사용하는 방법
(c) Microsoft Corporation 1998, All Rights Reserved. 기고: Leon Braginski, Microsoft Corporation

위로 가기

LIST