C/C++實(shí)現(xiàn)FTP文件上傳下載的示例詳解
FTP(文件傳輸協(xié)議)是一種用于在網(wǎng)絡(luò)上傳輸文件的標(biāo)準(zhǔn)協(xié)議。它屬于因特網(wǎng)標(biāo)準(zhǔn)化的協(xié)議族之一,為文件的上傳、下載和文件管理提供了一種標(biāo)準(zhǔn)化的方法,在Windows系統(tǒng)中操作FTP上傳下載可以使用WinINet庫(kù),WinINet(Windows Internet)庫(kù)是 Windows 操作系統(tǒng)中的一個(gè)網(wǎng)絡(luò) API 庫(kù),用于訪問(wèn) Internet 上的資源。它提供了一組函數(shù),使開(kāi)發(fā)人員能夠創(chuàng)建網(wǎng)絡(luò)應(yīng)用程序,例如通過(guò) HTTP 協(xié)議下載文件,發(fā)送 HTTP 請(qǐng)求,處理 cookie 等,本章將通過(guò)使用WinInet所提供的接口實(shí)現(xiàn)FTP文件上傳下載功能,使得用戶可以通過(guò)代碼的方式上傳或下載文件與FTP服務(wù)器交互。
首先讀者需要自行搭建FTP服務(wù)器,這里可以使用20CN Mini Ftp
這款迷你FTP服務(wù)器,配置好信息之后運(yùn)行即可;
接著來(lái)介紹實(shí)現(xiàn)FTP通信的標(biāo)準(zhǔn)API函數(shù)信息,其核心的函數(shù)如下所示;
InternetOpen
函數(shù),用于初始化 WinINet 庫(kù),返回一個(gè)句柄,該句柄可用于后續(xù)的網(wǎng)絡(luò)操作。以下是該函數(shù)的原型和簡(jiǎn)要說(shuō)明:
HINTERNET InternetOpen( LPCWSTR lpszAgent, // 用戶代理字符串,標(biāo)識(shí)應(yīng)用程序的名稱(chēng) DWORD dwAccessType, // 訪問(wèn)類(lèi)型,可以是 DIRECT、PRECONFIG 或 PROXY LPCWSTR lpszProxyName, // 代理服務(wù)器名稱(chēng) LPCWSTR lpszProxyBypass, // 代理服務(wù)器的繞過(guò)列表 DWORD dwFlags // 一些標(biāo)志,例如INTERNET_FLAG_ASYNC(異步操作) );
lpszAgent
: 用戶代理字符串,用于標(biāo)識(shí)應(yīng)用程序的名稱(chēng)??梢允菓?yīng)用程序的名稱(chēng)或標(biāo)識(shí)符。
dwAccessType
: 訪問(wèn)類(lèi)型,指定應(yīng)用程序的訪問(wèn)權(quán)限??梢允且韵轮抵唬?/p>
INTERNET_OPEN_TYPE_DIRECT
: 直接訪問(wèn)互聯(lián)網(wǎng)。INTERNET_OPEN_TYPE_PRECONFIG
: 使用系統(tǒng)配置的代理。INTERNET_OPEN_TYPE_PROXY
: 使用指定的代理。
lpszProxyName
: 代理服務(wù)器的名稱(chēng),僅在 dwAccessType
為 INTERNET_OPEN_TYPE_PROXY
時(shí)使用。
lpszProxyBypass
: 代理服務(wù)器的繞過(guò)列表,僅在 dwAccessType
為 INTERNET_OPEN_TYPE_PROXY
時(shí)使用。
dwFlags
: 一些標(biāo)志,用于指定其他選項(xiàng),例如 INTERNET_FLAG_ASYNC
表示執(zhí)行異步操作。
該函數(shù)返回一個(gè) HINTERNET
句柄,用于后續(xù)的網(wǎng)絡(luò)操作。如果操作失敗,返回 NULL
。在使用完 HINTERNET
句柄后,應(yīng)該使用 InternetCloseHandle
函數(shù)關(guān)閉該句柄。
InternetConnect
函數(shù),用于創(chuàng)建一個(gè)與指定服務(wù)器的連接。以下是該函數(shù)的原型和簡(jiǎn)要說(shuō)明:
HINTERNET InternetConnect( HINTERNET hInternet, // InternetOpen 返回的句柄 LPCWSTR lpszServerName, // 服務(wù)器的主機(jī)名 INTERNET_PORT nServerPort, // 服務(wù)器的端口號(hào) LPCWSTR lpszUsername, // 用戶名 LPCWSTR lpszPassword, // 密碼 DWORD dwService, // 服務(wù)類(lèi)型,例如 INTERNET_SERVICE_HTTP DWORD dwFlags, // 一些標(biāo)志,例如 INTERNET_FLAG_RELOAD DWORD_PTR dwContext // 應(yīng)用程序定義的上下文 );
hInternet
: 由 InternetOpen
返回的句柄,表示與 WinINet 庫(kù)的連接。
lpszServerName
: 服務(wù)器的主機(jī)名或 IP 地址。
nServerPort
: 服務(wù)器的端口號(hào)。
lpszUsername
: 連接需要的用戶名。
lpszPassword
: 連接需要的密碼。
dwService
: 服務(wù)類(lèi)型,可以是以下值之一:
INTERNET_SERVICE_FTP
: FTP 服務(wù)INTERNET_SERVICE_HTTP
: HTTP 服務(wù)- 其他服務(wù)類(lèi)型,具體可查閱官方文檔。
dwFlags
: 一些標(biāo)志,例如 INTERNET_FLAG_RELOAD
表示重新加載頁(yè)面。
dwContext
: 應(yīng)用程序定義的上下文,可以是一個(gè)指針。
該函數(shù)返回一個(gè) HINTERNET
句柄,用于后續(xù)的網(wǎng)絡(luò)操作。如果操作失敗,返回 NULL
。在使用完 HINTERNET
句柄后,應(yīng)該使用 InternetCloseHandle
函數(shù)關(guān)閉該句柄。
InternetWriteFile
函數(shù),用于向已打開(kāi)的互聯(lián)網(wǎng)文件或句柄寫(xiě)入數(shù)據(jù)。以下是該函數(shù)的原型和簡(jiǎn)要說(shuō)明:
BOOL InternetWriteFile( HINTERNET hFile, // 由 InternetOpenUrl 或 HttpOpenRequest 返回的文件句柄 LPCVOID lpBuffer, // 指向包含要寫(xiě)入的數(shù)據(jù)的緩沖區(qū)的指針 DWORD dwNumberOfBytesToWrite, // 要寫(xiě)入的字節(jié)數(shù) LPDWORD lpdwNumberOfBytesWritten // 指向接收實(shí)際寫(xiě)入的字節(jié)數(shù)的指針 );
hFile
: 由InternetOpenUrl
或HttpOpenRequest
返回的文件句柄。lpBuffer
: 指向包含要寫(xiě)入的數(shù)據(jù)的緩沖區(qū)的指針。dwNumberOfBytesToWrite
: 要寫(xiě)入的字節(jié)數(shù)。lpdwNumberOfBytesWritten
: 指向接收實(shí)際寫(xiě)入的字節(jié)數(shù)的指針。
該函數(shù)返回一個(gè)布爾值,指示操作是否成功。如果成功,返回 TRUE
,否則返回 FALSE
。
InternetReadFile
函數(shù),用于從已打開(kāi)的互聯(lián)網(wǎng)文件或句柄讀取數(shù)據(jù)。以下是該函數(shù)的原型和簡(jiǎn)要說(shuō)明:
BOOL InternetReadFile( HINTERNET hFile, // 由 InternetOpenUrl 或 HttpOpenRequest 返回的文件句柄 LPVOID lpBuffer, // 指向接收數(shù)據(jù)的緩沖區(qū)的指針 DWORD dwNumberOfBytesToRead, // 要讀取的字節(jié)數(shù) LPDWORD lpdwNumberOfBytesRead // 指向接收實(shí)際讀取的字節(jié)數(shù)的指針 );
hFile
: 由InternetOpenUrl
或HttpOpenRequest
返回的文件句柄。lpBuffer
: 指向接收數(shù)據(jù)的緩沖區(qū)的指針。dwNumberOfBytesToRead
: 要讀取的字節(jié)數(shù)。lpdwNumberOfBytesRead
: 指向接收實(shí)際讀取的字節(jié)數(shù)的指針。
該函數(shù)返回一個(gè)布爾值,指示操作是否成功。如果成功,返回 TRUE
,否則返回 FALSE
。
FTP文件下載
如下代碼是使用 WinInet 庫(kù)實(shí)現(xiàn)的 FTP 文件下載功能。以下是對(duì)該代碼的概述:
頭文件引入和庫(kù)鏈接:
- 代碼使用了
<Windows.h>
和<WinInet.h>
頭文件,同時(shí)通過(guò)#pragma comment(lib, "WinInet.lib")
鏈接了 WinInet 庫(kù),這是使用 WinInet 庫(kù)的基本準(zhǔn)備工作。
FtpSaveToFile 函數(shù):
該函數(shù)用于將數(shù)據(jù)保存到本地文件。它通過(guò)調(diào)用 CreateFile
創(chuàng)建一個(gè)空文件,然后使用 WriteFile
將數(shù)據(jù)寫(xiě)入文件,最后關(guān)閉文件句柄。這個(gè)函數(shù)在 FTP 文件下載后保存文件到本地。
FTPDownload 函數(shù):
- 這是主要的 FTP 下載函數(shù)。它使用 WinInet 提供的函數(shù)建立了一個(gè) FTP 會(huì)話,連接到指定的 FTP 服務(wù)器,打開(kāi)指定路徑的文件,并通過(guò)循環(huán)調(diào)用
InternetReadFile
讀取文件內(nèi)容。 - 下載的數(shù)據(jù)以字節(jié)數(shù)組的形式保存在
pDownloadData
中,下載完成后,調(diào)用FtpSaveToFile
函數(shù)將數(shù)據(jù)保存到本地文件。
注意事項(xiàng):
- 代碼中使用了
RtlZeroMemory
函數(shù)清空內(nèi)存,確保數(shù)據(jù)緩沖區(qū)的正確初始化。 - 注意釋放動(dòng)態(tài)分配的內(nèi)存,避免內(nèi)存泄漏。
函數(shù)參數(shù):
函數(shù)參數(shù)包括 FTP 服務(wù)器的主機(jī)名 (szHostName
)、用戶名 (szUserName
)、密碼 (szPassword
)、FTP 路徑 (szUrlPath
),以及本地保存路徑 (SavePath
)。
總體而言,這段代碼實(shí)現(xiàn)了基本的 FTP 文件下載功能,適用于從 FTP 服務(wù)器下載文件到本地。在使用時(shí),確保提供正確的 FTP 服務(wù)器信息和路徑,以及合適的本地保存路徑。
#include <iostream> #include <Windows.h> #include <WinInet.h> #pragma comment(lib, "WinInet.lib") // 保存文件到本地 BOOL FtpSaveToFile(char *pszFileName, BYTE *pData, DWORD dwDataSize) { // 創(chuàng)建空文件 HANDLE hFile = CreateFile(pszFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL); if (INVALID_HANDLE_VALUE == hFile) return FALSE; DWORD dwRet = 0; // 寫(xiě)出數(shù)據(jù)到文件 WriteFile(hFile, pData, dwDataSize, &dwRet, NULL); // 關(guān)閉句柄 CloseHandle(hFile); return TRUE; } BOOL FTPDownload(char *szHostName, char *szUserName, char *szPassword, char *szUrlPath, char *SavePath) { HINTERNET hInternet, hConnect, hFTPFile = NULL; BYTE *pDownloadData = NULL; DWORD dwDownloadDataSize = 0; DWORD dwBufferSize = 4096; BYTE *pBuf = NULL; DWORD dwBytesReturn = 0; DWORD dwOffset = 0; BOOL bRet = FALSE; // 建立會(huì)話并打開(kāi)FTP操作 hInternet = InternetOpen("WinInet Ftp", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); hConnect = InternetConnect(hInternet, szHostName, INTERNET_INVALID_PORT_NUMBER,szUserName, szPassword, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0); hFTPFile = FtpOpenFile(hConnect, szUrlPath, GENERIC_READ, FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD, NULL); // 獲取文件大小并初始化緩沖區(qū) dwDownloadDataSize = FtpGetFileSize(hFTPFile, NULL); pDownloadData = new BYTE[dwDownloadDataSize]; RtlZeroMemory(pDownloadData, dwDownloadDataSize); pBuf = new BYTE[dwBufferSize]; RtlZeroMemory(pBuf, dwBufferSize); // 循環(huán)接收數(shù)據(jù) do { // 讀取數(shù)據(jù) bRet = InternetReadFile(hFTPFile, pBuf, dwBufferSize, &dwBytesReturn); if (FALSE == bRet) break; // 將讀取到的數(shù)據(jù)追加到內(nèi)存 RtlCopyMemory((pDownloadData + dwOffset), pBuf, dwBytesReturn); dwOffset = dwOffset + dwBytesReturn; } while (dwDownloadDataSize > dwOffset); // 保存變量中的數(shù)據(jù)為文件 FtpSaveToFile(SavePath, pDownloadData, dwDownloadDataSize); // 釋放內(nèi)存 delete[]pDownloadData; pDownloadData = NULL; return TRUE; }
調(diào)用FTPDownload
時(shí)分別傳入?yún)?shù),參數(shù)1是IP地址,參數(shù)2是FTP登錄用戶名,參數(shù)3是FTP登錄密碼,參數(shù)4是服務(wù)器端根目錄下的文件,參數(shù)5是下載文件到本地的路徑,函數(shù)執(zhí)行結(jié)束后返回一個(gè)BOOL狀態(tài)值。
int main(int argc, char * argv[]) { BOOL bRET = FTPDownload("127.0.0.1", "admin", "admin", "/lyshark.jpg", "d://newtest/lyshark.jpg"); if (bRET == TRUE) { printf("已下載文件 \n"); } else { printf("下載失敗 \n"); } system("pause"); return 0; }
運(yùn)行后則可以將服務(wù)器端上的/lyshark.jpg
下載到本地的d://newtest/lyshark.jpg
目錄下,如下圖所示;
FTP文件上傳
如下代碼使用 WinInet 庫(kù)實(shí)現(xiàn)了 FTP 文件上傳操作。以下是對(duì)該代碼的概述:
函數(shù)功能:
該代碼實(shí)現(xiàn)了 FTP 文件上傳操作,將本地文件上傳到指定的 FTP 服務(wù)器路徑。
函數(shù)參數(shù):
函數(shù)參數(shù)包括 FTP 服務(wù)器的主機(jī)名 (szHostName
)、用戶名 (szUserName
)、密碼 (szPassword
)、FTP 路徑 (szUrlPath
),以及本地文件路徑 (FilePath
)。
建立會(huì)話和連接:
使用 InternetOpen
函數(shù)建立一個(gè) WinInet 會(huì)話,然后使用 InternetConnect
函數(shù)建立到 FTP 服務(wù)器的連接。
打開(kāi) FTP 文件:
使用 FtpOpenFile
函數(shù)打開(kāi)指定路徑的 FTP 文件。如果文件不存在,將創(chuàng)建一個(gè)新文件。文件以二進(jìn)制傳輸方式打開(kāi),并且具有重新加載標(biāo)志。
打開(kāi)本地文件:
使用 CreateFile
函數(shù)打開(kāi)本地文件。如果本地文件不存在,將返回 INVALID_HANDLE_VALUE
。
獲取文件大小和讀取文件數(shù)據(jù):
通過(guò) GetFileSize
獲取本地文件大小,然后根據(jù)文件大小動(dòng)態(tài)分配內(nèi)存,并使用 ReadFile
讀取文件數(shù)據(jù)到內(nèi)存中。
上傳數(shù)據(jù):
使用 InternetWriteFile
函數(shù)將內(nèi)存中的文件數(shù)據(jù)上傳到 FTP 服務(wù)器。上傳成功后釋放內(nèi)存,上傳失敗則返回 FALSE。
注意事項(xiàng):
- 確保提供正確的 FTP 服務(wù)器信息和路徑,以及本地文件路徑。
- 釋放動(dòng)態(tài)分配的內(nèi)存,避免內(nèi)存泄漏。
- 處理上傳失敗的情況,可能需要添加適當(dāng)?shù)腻e(cuò)誤處理代碼。
總體而言,這段代碼實(shí)現(xiàn)了基本的 FTP 文件上傳功能,適用于將本地文件上傳到 FTP 服務(wù)器。在使用時(shí),注意提供正確的參數(shù)和處理可能出現(xiàn)的錯(cuò)誤。
#include <iostream> #include <Windows.h> #include <WinInet.h> #pragma comment(lib, "WinInet.lib") // 實(shí)現(xiàn)文件上傳操作 BOOL FTPUpload(char *szHostName, char *szUserName, char *szPassword, char *szUrlPath, char *FilePath) { HINTERNET hInternet, hConnect, hFTPFile = NULL; DWORD dwBytesReturn = 0; DWORD UploadDataSize = 0; BYTE *pUploadData = NULL; DWORD dwRet, bRet = 0; // 建立會(huì)話并打開(kāi)FTP操作 hInternet = InternetOpen("WinInet Ftp", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); hConnect = InternetConnect(hInternet, szHostName, INTERNET_INVALID_PORT_NUMBER, szUserName, szPassword, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0); hFTPFile = FtpOpenFile(hConnect, szUrlPath, GENERIC_WRITE, FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD, NULL); // 打開(kāi)文件 HANDLE hFile = CreateFile(FilePath, GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE, NULL); if (INVALID_HANDLE_VALUE == hFile) return FALSE; // 獲取文件大小 UploadDataSize = GetFileSize(hFile, NULL); pUploadData = new BYTE[UploadDataSize]; // 讀取文件到緩沖區(qū) ReadFile(hFile, pUploadData, UploadDataSize, &dwRet, NULL); UploadDataSize = dwRet; // 開(kāi)始上傳數(shù)據(jù) bRet = InternetWriteFile(hFTPFile, pUploadData, UploadDataSize, &dwBytesReturn); if (FALSE == bRet) { delete[]pUploadData; return FALSE; } delete[]pUploadData; return TRUE; }
文件上傳與下載一樣,FTPUpload
通過(guò)傳入服務(wù)器地址,用戶名,密碼,上傳后的文件名,被上傳本地文件路徑;
int main(int argc, char * argv[]) { BOOL bRET = FTPUpload("127.0.0.1", "admin", "admin", "/abc.exe", "c://nc.exe"); if (bRET == TRUE) { printf("已上傳文件 \n"); } else { printf("上傳失敗 \n"); } system("pause"); return 0; }
上傳成功后輸出如下圖所示;
以上就是C/C++實(shí)現(xiàn)FTP文件上傳下載的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于C++ FTP文件上傳下載的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
VC實(shí)現(xiàn)ODBC數(shù)據(jù)庫(kù)操作實(shí)例解析
這篇文章主要介紹了VC實(shí)現(xiàn)ODBC數(shù)據(jù)庫(kù)操作的方法,非常有實(shí)用價(jià)值,需要的朋友可以參考下2014-07-07C++?OpenCV實(shí)現(xiàn)白平衡之完美反射算法
完美反射算法是白平衡各種算法中較常見(jiàn)的一種,比灰度世界算法更優(yōu)。本文將利用C++和OpenCV實(shí)現(xiàn)白平衡中的完美反射算法,需要的可以參考一下2022-05-05C 語(yǔ)言基礎(chǔ)教程(我的C之旅開(kāi)始了)[三]
C 語(yǔ)言基礎(chǔ)教程(我的C之旅開(kāi)始了)[三]...2007-02-02