使用libcurl下載檔案小例
阿新 • • 發佈:2019-02-11
libcurl是一個很強大的開源網路處理庫,支援包括HTTP、HTTPS、FTP……一系列網路協議。用它來進行HTTP的get\post 或者下載檔案更是小菜一碟,chrome核心都用到了它,本文主要講解一個使用curl下載檔案的小例。
首先是去下載curl的最新原始碼,然後編譯成動態庫或者靜態庫;然後把標頭檔案和庫檔案拿出來加入到我們自己的工程中,引用宣告:
特意在原有程式碼上加了一些註釋,希望可以更好理解,上程式碼:#include "curl.h" #ifdef _DEBUG #pragma comment(lib, "../Debug/libcurld") #else #pragma comment(lib, "../Release/libcurl") #endif
<pre name="code" class="cpp">// UseLibCurl.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include <Windows.h> #include <CommCtrl.h> #include "resource.h" #include "curl.h" #ifdef _DEBUG #pragma comment(lib, "../Debug/libcurld") #else #pragma comment(lib, "../Release/libcurl") #endif //這個用來儲存對話方塊的視窗控制代碼,因為後面要向這個視窗發訊息,必須知道其視窗控制代碼 HWND g_hDlgWnd = NULL; //提供給CURL下載進度回撥的函式,用於儲存下載的資料到檔案 static size_t DownloadCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam); //提供給CURL下載進度回撥的函式,用於計算下載進度通知介面 static int ProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); //這是對話方塊的訊息迴圈,在控制檯程式裡面建立GUI,僅僅是為了更好地展現下載回撥這個功能 INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //這個是下載的執行緒函式,為了不把對話方塊主介面卡死,肯定是要自己開執行緒來下載的了 DWORD WINAPI DownloadThread(LPVOID lpParam); int _tmain(int argc, _TCHAR* argv[]) { //彈出對話方塊,知道對話方塊關閉才會執行退出 DialogBox(NULL, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc ); return 0; } static size_t DownloadCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam) { //把下載到的資料以追加的方式寫入檔案(一定要有a,否則前面寫入的內容就會被覆蓋了) FILE* fp = NULL; fopen_s(&fp, "c:\\test.apk", "ab+"); size_t nWrite = fwrite(pBuffer, nSize, nMemByte, fp); fclose(fp); return nWrite; } static int ProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { if ( dltotal > -0.1 && dltotal < 0.1 ) return 0; int nPos = (int) ( (dlnow/dltotal)*100 ); //通知進度條更新下載進度 ::PostMessage(g_hDlgWnd, WM_USER + 110, nPos, 0); //::Sleep(10); return 0; } INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch( uMsg ) { case WM_INITDIALOG: { g_hDlgWnd = hWnd; HWND hProgress = GetDlgItem(hWnd, IDC_PROGRESS1); SendMessage(hProgress, PBM_SETRANGE32, (WPARAM) 0, (LPARAM) 100); //對話方塊初始化時建立下載執行緒 HANDLE hThread = CreateThread(NULL, 0, DownloadThread, 0, 0, NULL); CloseHandle(hThread); ::SetWindowText(hWnd, L"使用CURL下載檔案示例:"); return TRUE; } case WM_COMMAND: { WORD msg = HIWORD(wParam); WORD id = LOWORD(wParam); if ( id == IDOK || id == IDCANCEL ) EndDialog(hWnd, id); break; } case WM_ERASEBKGND: return TRUE; case WM_CTLCOLORSTATIC: return (INT_PTR)(HBRUSH)::GetStockObject(WHITE_BRUSH); case WM_USER + 110: {//接收到設定進度的訊息 HWND hProgress = GetDlgItem(hWnd, IDC_PROGRESS1); HWND hStatus = GetDlgItem(hWnd, IDC_STATUS); if ( hProgress ) SendMessage(hProgress, PBM_SETPOS, wParam, 0L); if ( hStatus ) { WCHAR szBuffer[100] = {0}; if ( wParam<100 ) swprintf(szBuffer, L"正在下載檔案,進度:%d%%", wParam); else swprintf(szBuffer, L"檔案下載完畢!"); ::SetWindowText(hStatus, szBuffer); } return 0; } default: break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } DWORD WINAPI DownloadThread(LPVOID lpParam) { //初始化curl,這個是必須的 CURL* curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, "http://android.shoujids.com/software/download?id=154103"); //設定接收資料的回撥 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DownloadCallback); //curl_easy_setopt(curl, CURLOPT_INFILESIZE, lFileSize); //curl_easy_setopt(curl, CURLOPT_HEADER, 1); //curl_easy_setopt(curl, CURLOPT_NOBODY, 1); //curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); // 設定重定向的最大次數 curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5); // 設定301、302跳轉跟隨location curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); //設定進度回撥函式 curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, ProgressCallback); //curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &lFileSize); //curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, g_hDlgWnd); //開始執行請求 CURLcode retcCode = curl_easy_perform(curl); //檢視是否有出錯資訊 const char* pError = curl_easy_strerror(retcCode); //清理curl,和前面的初始化匹配 curl_easy_cleanup(curl); return 0; }
執行效果圖: