C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[184] [팁] HTTP로 파일 다운받기 (WinInet 이용)
박지훈.임프 [cbuilder] 10683 읽음    2001-08-24 17:48
임프랍니다.

다음은 IE의 일부로 윈도우즈의 모든 버전에 설치되어 있는 WinInet API를 이용하여 웹 상의 파일을
다운받는 소스입니다. 옛날에 작성한 거라서 기억이 가물거리지만, MSDN에서 긁어온 것을 약간 수정한 것
같네요.

//---------------------------------------------------------------------------
#include 
#pragma hdrstop

#include "Unit1.h"
#include "wininet.h"            // WinInet 헤더 인클루드 
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#pragma link "wininet.lib"      // WinInet 라이브러리 링크 
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

bool __fastcall GetHttpFile(AnsiString StrUrl, TStream *Stream)
{
    Stream->Position = 0;

    HINTERNET ISession = InternetOpen(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    HINTERNET HttpFile = InternetOpenUrl(ISession, StrUrl.c_str(), NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
    AnsiString UrlBuff;
    UrlBuff.SetLength(1024);
    DWord BuffSize = 1024;
    if(HttpQueryInfo(HttpFile, HTTP_QUERY_CONTENT_LOCATION, UrlBuff.c_str(), &BuffSize, NULL)==false)
    {
        switch(GetLastError())
        {
            case ERROR_INSUFFICIENT_BUFFER:
            UrlBuff.SetLength(BuffSize+1);
            HttpQueryInfo(HttpFile, HTTP_QUERY_CONTENT_LOCATION, UrlBuff.c_str(), &BuffSize, 0);
            break;

            case ERROR_HTTP_HEADER_NOT_FOUND:
            UrlBuff = StrUrl;
            break;

            default:
            InternetCloseHandle(HttpFile);
            return false;
        }
    }
    char FileSizeBuff[4];
    BuffSize = sizeof(FileSizeBuff);
    bool bSizeIsKnown = HttpQueryInfo(HttpFile, HTTP_QUERY_CONTENT_LENGTH, &FileSizeBuff, &BuffSize, NULL);
    bool Result;
    DWord FileSize;
    if(bSizeIsKnown)
    {
        FileSize = atol(FileSizeBuff);
        TMemoryStream *ms;
        ms = dynamic_cast(Stream);
        if(ms == NULL)
            ms = new TMemoryStream;
        ms->Size = FileSize;
        DWord ByteRead;
        Result = InternetReadFile(HttpFile, ms->Memory, FileSize, &ByteRead);
        if(Result) Stream->CopyFrom(ms, 0);
        if(ms != Stream) delete ms;
    }
    else
    {
        void *Buffer = new char[2048];
        FileSize = 2048;
        DWord ByteRead;
        while(true)
        {
            Result = InternetReadFile(HttpFile, Buffer, FileSize, &ByteRead);
            if(ByteRead == 0) break;
            Stream->WriteBuffer(Buffer, ByteRead);
        }
        delete Buffer; 
    }
    InternetCloseHandle(HttpFile);
    InternetCloseHandle(ISession);
    return Result;
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TStringStream *ss = new TStringStream("");
    AnsiString StrUrl = UrlEdit->Text;
    if(GetHttpFile(UrlEdit->Text, ss))
        RichEdit1->Lines->Text = ss->DataString;
    else
        ShowMessage("Error"); 
    delete ss;
}


이 소스의 GetHttpFile() 함수는 첫번째 인자를 안시스트링 포맷의 URL, 그리고 두번째 인자로서 스트림
클래스를 받도록 되어있습니다. 다운받을 파일이 HTML이나 텍스트등 텍스트 포맷이면 예에서 보인 것처럼
TStringStream을 쓰는 것이 편할 것이고, 바이너리 파일이라면 TFileStream을 쓰는 것이 좋을 겁니다.

그럼 이만...
아제나 [azena]   2009-01-19 10:29 X
43 라인에,
InternetCloseHandle(ISession);
추가해주세요. 오류나면 다음부터 세션 안 열립니다;;;
강재호.만해 [greenuri]   2010-09-07 06:36 X
75 라인에
delete Buffer; -> delete [] Buffer; 로 수정해주세요
메모리 누수 오류 납니다.

+ -

관련 글 리스트
184 [팁] HTTP로 파일 다운받기 (WinInet 이용) 박지훈.임프 10683 2001/08/24
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.