簡體   English   中英

使用 Libcurl 庫進行文件下載

[英]Using Libcurl library for file download

我正在嘗試通過從 Dropbox 或谷歌驅動器中的共享鏈接下載更新文件來實現自動更新。 一開始,我使用windows API函數URLDownloadToFile()從網上下載公共文件。 它工作正常,但是當我將它用於雲文件時,它沒有下載文件。 而是獲取一個 HTML 文件,當使用瀏覽器打開時,我可以使用瀏覽器下載該文件。

因此,我轉而使用 Libcurl 庫並按照他們的教程進行操作。 我總是收到錯誤

(60) : CURL_PEER_FAILED_VERIFICATION。

我按照https://curl.haxx.se/libcurl/c/url2file.html 中的示例進行操作。 並嘗試獲取相同的公共文件,我已經下載了 Windows API,但仍然收到相同的錯誤。 所以我知道它與服務器身份驗證或類似問題無關。

這是我使用 windows api 和 Libcurl 的下載功能:

static size_t write_data (void *ptr,size_t size,size_t nmemb,void* stream)
{
  size_t written = fwrite (ptr,size,nmemb,(FILE *) stream) ;
  return written ;
} /* write_data */


int DownloadFile ()
{
  static const char FileURL[] = "https://www.pexels.com/photo/618608/download/?search_query=park&tracking_id=6qgsqm6nzau" :
  static char TargetURL[]  = "D:\\Download\\DownloadURL\\Test.jpg" ;
  static char TargetCURL[] = "D:\\Download\\DownloadCURL\\Test.jpg" ;

  // Download the file using windows function into DownloadURL folder
  URLDownloadToFile (nullptr,FileURL[2],TargetURL,0,nullptr) ; // OK

  // Download the file using curl library into DownloadCURL folder
  if (auto curl = curl_easy_init ()) {
      auto fp = fopen (TargetCURL,"wb") ;
      curl_easy_setopt (curl,CURLOPT_URL,FileURL[1]) ;
      curl_easy_setopt (curl,CURLOPT_FAILONERROR,1) ;
      curl_easy_setopt (curl,CURLOPT_WRITEDATA,fp) ;

      /* Perform the request, res will get the return code */
      auto res = curl_easy_perform (curl) ;                     // Always Fail

      fclose (fp) ;
      curl_easy_cleanup (curl) ;
  } /* if (auto curl = curl_easy_init ()) */

  return true ;

} /* Download */

我的系統運行的是 Windows 10 x64。 我使用帶有 openSSL 的 Visual Studio 2017,Libcurl 修訂版 7.67。

誰能幫我弄清楚缺少什么?

您使用的 URL 重定向到此 URL: https://images.pexels.com/photos/618608/pexels-photo-618608.jpeg?cs=srgb&dl=worm-s-eyeview-of-tall-tree-under-a-gray-sky-618608.jpg&fm=jpg : https://images.pexels.com/photos/618608/pexels-photo-618608.jpeg?cs=srgb&dl=worm-s-eyeview-of-tall-tree-under-a-gray-sky-618608.jpg&fm=jpg所以你需要在 curl 中啟用以下重定向:

curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // follow redirects

您還需要提供write_data函數:

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);


curl_easy_setopt (curl,CURLOPT_URL,FileURL[1]) ;
應該
curl_easy_setopt (curl,CURLOPT_URL,FileURL);

如果您在 http 代理后面,您可能還需要
curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L);

#include "curl/curl.h"
#include <cstdio>

static size_t write_data(void* ptr, size_t size, size_t nmemb, void* stream) {
    size_t written = fwrite(ptr, size, nmemb, static_cast<FILE*>(stream));
    return written;
} /* write_data */

bool DownloadFile() {
    bool retval = false;
    static const char FileURL[] =
        "https://www.pexels.com/photo/618608/download/"
        "?search_query=park&tracking_id=6qgsqm6nzau";
    static char TargetCURL[] = "D:\\Download\\DownloadCURL\\Test.jpg";

    // Download the file using curl library into DownloadCURL folder
    if(CURL* curl = curl_easy_init()) {
        if(FILE* fp = fopen(TargetCURL, "wb")) {
            curl_easy_setopt(curl, CURLOPT_URL, FileURL);
            curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
            curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // follow redirects
            curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L); // corp. proxies etc.

            /* Perform the request, res will get the return code */
            CURLcode res = curl_easy_perform(curl);
            if(!res) retval = true;

            fclose(fp);
        }
        curl_easy_cleanup(curl);
    } /* if (auto curl = curl_easy_init ()) */

    return retval;

} /* Download */

int main() {
    CURLcode res = curl_global_init(CURL_GLOBAL_ALL);
    if(res) return 1;
    DownloadFile();
    curl_global_cleanup();
}

該錯誤與 TLS 證書頒發者驗證有關。 您缺少服務器的 CA 證書。 在 Windows 上,默認情況下 OpenSSL 帶有一個空的證書存儲。 在 Windows 上最好使用 schannel 支持而不是 OpenSSL 編譯 libcurl,然后它將使用 Windows 內置證書存儲。

您需要設置這些選項:

curl_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0); 

也許你可以試試teemo庫,它基於 libcurl,並且支持多線程下載

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM