티스토리 뷰

프로그래밍/API

FTP Client

에어버스 2020. 4. 19. 13:08

 

FTP Client, FTP 클라이언트, FTP 전송

MFC로 FTP 프로그램을 만들면 PutFile()와 같이 파일명만 지정하면 전송되므로 진행상태를 알 수 없다.

그래서 WIN32 API를 이용한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
bool CStock64Dlg::파일전송3(CString str파일명, BOOL bIsTXT파일) // TXT, DB 파일을 전송
{
    HINTERNET hRemote, hFtp, hInternet;
    HANDLE hLocal;
    DWORD dwRead, dwWritten, dwWriteSize;
    BOOL Result;
    TCHAR* buf;
    __int64 fileSize, Prog = 0;
    hRemote = hFtp = hLocal = hInternet = NULL;
 
 
    CString drv, dir, fn, fe, strCount;
    CString strLocal파일, strRemote파일, strFTP시작, strFTP완료, strPutFile, str파일구분, strRemoteFile;
 
    if (TRUE == bIsTXT파일)
    {
        str파일구분 = TEXT("TXT");
        strRemoteFile = _FTP_REMOTE_PATH_TXT;
    }
    else
    {
        str파일구분 = TEXT("DB");
        strRemoteFile = _FTP_REMOTE_PATH_DB;
    }
 
    //////////////////    
    strLocal파일 = str파일명;
    _tsplitpath_s(strLocal파일, drv.GetBuffer(10), _MAX_DRIVE, dir.GetBuffer(_MAX_PATH), _MAX_DIR, fn.GetBuffer(_MAX_PATH), _MAX_FNAME, fe.GetBuffer(_MAX_PATH), _MAX_EXT);
    strRemote파일.Format(TEXT("%s\\%s%s%s"), strRemoteFile, fn, fe, _압축파일명확장자);
    dir.ReleaseBuffer();
    drv.ReleaseBuffer();
    fn.ReleaseBuffer();
    fe.ReleaseBuffer();
    //////////////////
    
    fileSize = 파일크기얻기(strLocal파일 + _압축파일명확장자);
    if (0 >= fileSize)
        return false;
 
    DWORD nVal = DWORD(fileSize / 10); // 최소 10번 나눠 전송한다.
    if (nVal > _FILE_BUF_SIZE)
        nVal = _FILE_BUF_SIZE;
    //__int64 nSize = INT64(fileSize / nVal); // 반복횟수
 
    try {
        buf = new TCHAR[nVal]; //TCHAR buf[FTP_FILE_HANDLING_SIZE];
    }
    catch (std::bad_alloc& rErr) // STL 제공
    {
        AfxMessageBox(TEXT("CStock64Dlg::파일전송3 : 동적할당 실패!\n\n"+ CString(rErr.what()));
        return false;
    }
 
    int nPercent, nPrevPercent = -1;
    
    CInternetSession sess(_T("My FTP Session"+ str파일구분);
    CString strID = theApp.GetFTPID();
    CString strPWD = theApp.GetFTPPWD();
 
    hInternet = InternetOpen(TEXT("Stock64 FTP"+ str파일구분, INTERNET_OPEN_TYPE_PRECONFIG, NULLNULL0);
    if (NULL == hInternet)
    {
        AfxMessageBox("FTP 초기화 실패!!!");
        return false;
    }
    hFtp = InternetConnect(hInternet, _FTP서버, INTERNET_DEFAULT_FTP_PORT, strID, strPWD, INTERNET_SERVICE_FTP, 00);
    if (NULL == hFtp) {
        InternetCloseHandle(hInternet);
        텔레그램전송(TEXT("FTP서버 연결실패!!!"));
        AfxMessageBox(TEXT("FTP 서버 로그인 실패!!!"));
        return false;
    }
       
    // 서버에 파일을 만든다.
    //lstrcat(Remote, ext);
    hRemote = FtpOpenFile(hFtp, strRemote파일, GENERIC_WRITE, FTP_TRANSFER_TYPE_BINARY, 0); //hRemote = FtpOpenFile(hFtp, Remote, GENERIC_WRITE, FTP_TRANSFER_TYPE_BINARY, 0);
    if (hRemote == NULL)
    {
        AfxMessageBox(strRemote파일 + TEXT("서버에 파일 만들기 실패"));
        return false;
    }
 
    //로컬 파일을 연다
    hLocal = CreateFile(strLocal파일 + _압축파일명확장자, GENERIC_READ, 0NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //hLocal = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == hLocal)
    {
        AfxMessageBox(strLocal파일 + _압축파일명확장자 + TEXT("\n로컬 파일 열기 실패"));
        return false;
    }
 
    //FTP_FILE_HANDLING_SIZE바이트씩 올리며, 진행 상태를 출력한다. 
    
 
    텔레그램전송(strFTP시작);
    SetDlgItemText(IDC_STATIC_COUNT_SAVE, strFTP시작);
    m_ctlProgress.SetRange(0100);
    m_ctlProgress.SetPos(0); // 파일 압축이 끝나서 초기화
 
    while (fileSize != Prog)
    {
        Result = ReadFile(hLocal, buf, nVal, &dwRead, NULL);
        if (FALSE == Result)
        {
            AfxMessageBox(ErrorMsg(TEXT("FTP 파일읽기 실패 : ")));
            return false;
        }
        else if (0 == dwRead) // 더 이상 전송할 데이터가 없는 경우
            break;
 
        if (FALSE == InternetWriteFile(hRemote, buf, dwWriteSize, &dwWritten)) // FTP 전송
        {
            int nErrorCode = GetLastError();
            LPVOID lpMsgBuf;
            FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
                FORMAT_MESSAGE_IGNORE_INSERTS, NULL, nErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                (LPTSTR)&lpMsgBuf, 0NULL);
            CString str2; str2.Format(TEXT("FTP전송 실패 : %s\n%s"), strLocal파일 + _압축파일명확장자, LPTSTR(&lpMsgBuf));
            AfxMessageBox(str2);
            LocalFree(lpMsgBuf);
        }
        ZeroMemory(buf, nVal);
        Prog += dwWritten;
 
        nPercent = int((Prog / double(fileSize)) * 100.0); // float 형변환이 없으면 계산값이 0 이 된다.
        //////////////////////
        // 파일을 10MB로 작은 단위로 보낼때는 필요하지만, 4GB로 보낼때는 구분할 필요가 없을듯하여 주석처리함.
        //if ((m_bBigFile == _bDBfile && FALSE == bIsTXT파일) // 큰파일이 DB인 경우
        //    || (m_bBigFile == _bTXTfile && TRUE == bIsTXT파일)) // 또는 큰파일이 TXT인 경우
        {
            if (nPercent <= nPrevPercent)
                continue;
            m_ctlProgress.SetPos(nPercent);
            strCount.Format(TEXT("%s FTP : %d%%"), str파일구분, nPercent);
            SetDlgItemText(IDC_STATIC_COUNT_SAVE, strCount);
            nPrevPercent = nPercent;
        }
        //////////////////////                
    }
    CloseHandle(hLocal);
    InternetCloseHandle(hRemote);
    InternetCloseHandle(hFtp);
    InternetCloseHandle(hInternet);
 
    delete[] buf;
 
    if (fileSize != Prog)
    {
        AfxMessageBox(TEXT("원본파일과 전송파일 크기가 다릅니다."));
        return false;
    }
 
    SetDlgItemText(IDC_STATIC_COUNT_SAVE, strFTP완료);
 
    ::DeleteFile(strLocal파일);
    if (::DeleteFile(strLocal파일 + _압축파일명확장자) == false)
        AfxMessageBox(strLocal파일 + _압축파일명확장자 + TEXT("삭제 실패"));
 
    if (TRUE == bIsTXT파일)
        m_bTXT전송완료 = TRUE;
    else
        m_bDB전송완료 = TRUE;
 
    if (TRUE == m_bTXT전송완료 && TRUE == m_bDB전송완료)
    {
        m_ctlProgress.SetPos(0);
        GetDlgItem(IDC_STATIC_COUNT_SAVE)->SetWindowText(TEXT("FTP 모두 완료"));
    }
    return true;
}
cs

 

아래 코드로 하면 서버에 전송파일이 안 만들어진다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "wininet.h"
 
HINTERNET hInternet, hFtp;
bool FtpConnect(const char *host, const char *user, const char *pwd, int port)
{
 hInternet = InternetOpen("FTPTEST", INTERNET_OPEN_TYPE_PRECONFIG, NULLNULL0);
 if(hInternet == NULL){
  return false;
 }
 hFtp = InternetConnect(hInternet, host, INTERNET_DEFAULT_FTP_PORT, user, pwd, INTERNET_SERVICE_FTP, 00);
 if(hFtp == NULL){
  InternetCloseHandle(hInternet);
  return false;
 }
 return true;
}
 
void FtpDisconnect(void)
{
 InternetCloseHandle(hFtp);
 InternetCloseHandle(hInternet);
 hFtp = NULL;
 hInternet = NULL;
}
 
void FtpEnumFiles(void)
{
 WIN32_FIND_DATA wfd;
 BOOL bResult = TRUE;
 HINTERNET hFind;
 if(hFtp == NULL)
  return;
 hFind = FtpFindFirstFile(hFtp, "*.*"&wfd, 00);
 if(hFind != NULL){
  do{
   if(wfd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
    printf("[Folder] %s\n", wfd.cFileName);
   else
    printf("[File] %s\n", wfd.cFileName);
   bResult = InternetFindNextFile(hFind, &wfd);
  }while(bResult);
  InternetCloseHandle(hFind);
 }
}
 
BOOL FtpDownLoad(const char *destPath, const char *downloadName)
{
 TCHAR NewFile[MAX_PATH];
   wsprintf(NewFile, "%s\\%s", destPath, downloadName);
  return FtpGetFile(hFtp, downloadName, NewFile, FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD, 0);
}
 
BOOL FtpDownLoadBigFile(const char *destPath, const char *downloadName)
{
 HINTERNET hRemote;
 HANDLE hLocal;
 DWORD dwRead, dwWritten, Prog, filesize;
 BOOL Result;
 TCHAR NewFile[MAX_PATH];
 TCHAR buf[FTP_FILE_HANDLING_SIZE];
 
 //서버의 파일을 오픈한다. 
 hRemote = FtpOpenFile(hFtp, downloadName, GENERIC_READ, FTP_TRANSFER_TYPE_BINARY, 0);
 if(hRemote == NULL){
 printf("   --->download FAIL due to FtpOpenFile!!!: %s\n", downloadName);
  return FALSE;
 }
 
 //파일 사이즈를 구한다
 filesize = FtpGetFileSize(hRemote, NULL);
 //로컬 파일을 만든다. 
 wsprintf(NewFile, "%s\\%s", destPath, downloadName);
 hLocal = CreateFile(NewFile, GENERIC_WRITE, 0NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 //FTP_FILE_HANDLING_SIZE바이트씩 받으며 진행 상태를 출력한다. 
 Prog = 0;
 for(;;){
  Result = InternetReadFile(hRemote, buf, FTP_FILE_HANDLING_SIZE, &dwRead);
  if( (Result == TRUE) && (dwRead == 0) )
   break;
  WriteFile(hLocal, buf, dwRead,  &dwWritten, NULL);
  Prog += dwWritten;
  printf("%s (%d bytes / %d bytes)", downloadName, filesize,  Prog);  
 }
 CloseHandle(hLocal);
 InternetCloseHandle(hRemote);
 return TRUE;
}
 
BOOL FtpUpLoad(const char *path)
{
 BOOL bRet = FALSE;
 TCHAR ext[_MAX_EXT];
 TCHAR Remote[MAX_PATH];
 _splitpath(path, NULLNULL, Remote, ext);
 lstrcat(Remote, ext);
 bRet = FtpPutFile(hFtp, path, Remote, FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD, 0);
 if(bRet == FALSE)
  printf("FtpPutFile failed....\n");
 return bRet;
}
 
BOOL FtpUpLoadBigFile(const char *path)
{
 HINTERNET hRemote;
 HANDLE hLocal;
 TCHAR ext[_MAX_EXT];
 TCHAR Remote[MAX_PATH];
 DWORD dwRead, dwWritten, Prog;
 BOOL Result;
 TCHAR buf[FTP_FILE_HANDLING_SIZE];
 TCHAR str[255];
 
 //서버에 파일을 만든다
 _splitpath(path, NULLNULL, Remote, ext);
 lstrcat(Remote, ext);
 hRemote = FtpOpenFile(hFtp, Remote, GENERIC_WRITE, FTP_TRANSFER_TYPE_BINARY, 0);
 if(hRemote == NULL)
  return FALSE;
 //로컬 파일을 연다
 hLocal = CreateFile(path, GENERIC_READ, 0NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 //FTP_FILE_HANDLING_SIZE바이트씩 올리며, 진행 상태를 출력한다. 
 Prog = 0;
 for(;;){
  Result = ReadFile(hLocal, buf, FTP_FILE_HANDLING_SIZE, &dwRead, NULL);
  if((Result == TRUE) && (dwRead == 0))
   break;
  InternetWriteFile(hRemote, buf, FTP_FILE_HANDLING_SIZE, &dwWritten);
  Prog += dwWritten;
  printf("%s (%ld bytes / %ld bytes)", path, filesize, Prog); // filesize는 별도로 구해야 함
 }
 CloseHandle(hLocal);
 InternetCloseHandle(hRemote);
 return TRUE;
cs

출처 : http://blog.naver.com/PostView.nhn?blogId=ybchoi75&logNo=221323529111

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31