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庫,WinINet(Windows Internet)庫是 Windows 操作系統(tǒng)中的一個(gè)網(wǎng)絡(luò) API 庫,用于訪問 Internet 上的資源。它提供了一組函數(shù),使開發(fā)人員能夠創(chuàng)建網(wǎng)絡(luò)應(yīng)用程序,例如通過 HTTP 協(xié)議下載文件,發(fā)送 HTTP 請(qǐng)求,處理 cookie 等,本章將通過使用WinInet所提供的接口實(shí)現(xiàn)FTP文件上傳下載功能,使得用戶可以通過代碼的方式上傳或下載文件與FTP服務(wù)器交互。
首先讀者需要自行搭建FTP服務(wù)器,這里可以使用20CN Mini Ftp這款迷你FTP服務(wù)器,配置好信息之后運(yùn)行即可;
接著來介紹實(shí)現(xiàn)FTP通信的標(biāo)準(zhǔn)API函數(shù)信息,其核心的函數(shù)如下所示;
InternetOpen 函數(shù),用于初始化 WinINet 庫,返回一個(gè)句柄,該句柄可用于后續(xù)的網(wǎng)絡(luò)操作。以下是該函數(shù)的原型和簡(jiǎn)要說明:
HINTERNET InternetOpen( LPCWSTR lpszAgent, // 用戶代理字符串,標(biāo)識(shí)應(yīng)用程序的名稱 DWORD dwAccessType, // 訪問類型,可以是 DIRECT、PRECONFIG 或 PROXY LPCWSTR lpszProxyName, // 代理服務(wù)器名稱 LPCWSTR lpszProxyBypass, // 代理服務(wù)器的繞過列表 DWORD dwFlags // 一些標(biāo)志,例如INTERNET_FLAG_ASYNC(異步操作) );
lpszAgent: 用戶代理字符串,用于標(biāo)識(shí)應(yīng)用程序的名稱??梢允菓?yīng)用程序的名稱或標(biāo)識(shí)符。
dwAccessType: 訪問類型,指定應(yīng)用程序的訪問權(quán)限??梢允且韵轮抵唬?/p>
INTERNET_OPEN_TYPE_DIRECT: 直接訪問互聯(lián)網(wǎng)。INTERNET_OPEN_TYPE_PRECONFIG: 使用系統(tǒng)配置的代理。INTERNET_OPEN_TYPE_PROXY: 使用指定的代理。
lpszProxyName: 代理服務(wù)器的名稱,僅在 dwAccessType 為 INTERNET_OPEN_TYPE_PROXY 時(shí)使用。
lpszProxyBypass: 代理服務(wù)器的繞過列表,僅在 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)要說明:
HINTERNET InternetConnect( HINTERNET hInternet, // InternetOpen 返回的句柄 LPCWSTR lpszServerName, // 服務(wù)器的主機(jī)名 INTERNET_PORT nServerPort, // 服務(wù)器的端口號(hào) LPCWSTR lpszUsername, // 用戶名 LPCWSTR lpszPassword, // 密碼 DWORD dwService, // 服務(wù)類型,例如 INTERNET_SERVICE_HTTP DWORD dwFlags, // 一些標(biāo)志,例如 INTERNET_FLAG_RELOAD DWORD_PTR dwContext // 應(yīng)用程序定義的上下文 );
hInternet: 由 InternetOpen 返回的句柄,表示與 WinINet 庫的連接。
lpszServerName: 服務(wù)器的主機(jī)名或 IP 地址。
nServerPort: 服務(wù)器的端口號(hào)。
lpszUsername: 連接需要的用戶名。
lpszPassword: 連接需要的密碼。
dwService: 服務(wù)類型,可以是以下值之一:
INTERNET_SERVICE_FTP: FTP 服務(wù)INTERNET_SERVICE_HTTP: HTTP 服務(wù)- 其他服務(wù)類型,具體可查閱官方文檔。
dwFlags: 一些標(biāo)志,例如 INTERNET_FLAG_RELOAD 表示重新加載頁面。
dwContext: 應(yīng)用程序定義的上下文,可以是一個(gè)指針。
該函數(shù)返回一個(gè) HINTERNET 句柄,用于后續(xù)的網(wǎng)絡(luò)操作。如果操作失敗,返回 NULL。在使用完 HINTERNET 句柄后,應(yīng)該使用 InternetCloseHandle 函數(shù)關(guān)閉該句柄。
InternetWriteFile 函數(shù),用于向已打開的互聯(lián)網(wǎng)文件或句柄寫入數(shù)據(jù)。以下是該函數(shù)的原型和簡(jiǎn)要說明:
BOOL InternetWriteFile( HINTERNET hFile, // 由 InternetOpenUrl 或 HttpOpenRequest 返回的文件句柄 LPCVOID lpBuffer, // 指向包含要寫入的數(shù)據(jù)的緩沖區(qū)的指針 DWORD dwNumberOfBytesToWrite, // 要寫入的字節(jié)數(shù) LPDWORD lpdwNumberOfBytesWritten // 指向接收實(shí)際寫入的字節(jié)數(shù)的指針 );
hFile: 由InternetOpenUrl或HttpOpenRequest返回的文件句柄。lpBuffer: 指向包含要寫入的數(shù)據(jù)的緩沖區(qū)的指針。dwNumberOfBytesToWrite: 要寫入的字節(jié)數(shù)。lpdwNumberOfBytesWritten: 指向接收實(shí)際寫入的字節(jié)數(shù)的指針。
該函數(shù)返回一個(gè)布爾值,指示操作是否成功。如果成功,返回 TRUE,否則返回 FALSE。
InternetReadFile 函數(shù),用于從已打開的互聯(lián)網(wǎng)文件或句柄讀取數(shù)據(jù)。以下是該函數(shù)的原型和簡(jiǎn)要說明:
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 庫實(shí)現(xiàn)的 FTP 文件下載功能。以下是對(duì)該代碼的概述:
頭文件引入和庫鏈接:
- 代碼使用了
<Windows.h>和<WinInet.h>頭文件,同時(shí)通過#pragma comment(lib, "WinInet.lib")鏈接了 WinInet 庫,這是使用 WinInet 庫的基本準(zhǔn)備工作。
FtpSaveToFile 函數(shù):
該函數(shù)用于將數(shù)據(jù)保存到本地文件。它通過調(diào)用 CreateFile 創(chuàng)建一個(gè)空文件,然后使用 WriteFile 將數(shù)據(jù)寫入文件,最后關(guān)閉文件句柄。這個(gè)函數(shù)在 FTP 文件下載后保存文件到本地。
FTPDownload 函數(shù):
- 這是主要的 FTP 下載函數(shù)。它使用 WinInet 提供的函數(shù)建立了一個(gè) FTP 會(huì)話,連接到指定的 FTP 服務(wù)器,打開指定路徑的文件,并通過循環(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;
// 寫出數(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ì)話并打開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 庫實(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ù)器的連接。
打開 FTP 文件:
使用 FtpOpenFile 函數(shù)打開指定路徑的 FTP 文件。如果文件不存在,將創(chuàng)建一個(gè)新文件。文件以二進(jìn)制傳輸方式打開,并且具有重新加載標(biāo)志。
打開本地文件:
使用 CreateFile 函數(shù)打開本地文件。如果本地文件不存在,將返回 INVALID_HANDLE_VALUE。
獲取文件大小和讀取文件數(shù)據(jù):
通過 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ì)話并打開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);
// 打開文件
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;
// 開始上傳數(shù)據(jù)
bRet = InternetWriteFile(hFTPFile, pUploadData, UploadDataSize, &dwBytesReturn);
if (FALSE == bRet)
{
delete[]pUploadData;
return FALSE;
}
delete[]pUploadData;
return TRUE;
}
文件上傳與下載一樣,FTPUpload通過傳入服務(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ù)庫操作實(shí)例解析
這篇文章主要介紹了VC實(shí)現(xiàn)ODBC數(shù)據(jù)庫操作的方法,非常有實(shí)用價(jià)值,需要的朋友可以參考下2014-07-07
C++?OpenCV實(shí)現(xiàn)白平衡之完美反射算法
完美反射算法是白平衡各種算法中較常見的一種,比灰度世界算法更優(yōu)。本文將利用C++和OpenCV實(shí)現(xiàn)白平衡中的完美反射算法,需要的可以參考一下2022-05-05

