【问题标题】:C++ 'GET' request or how do you download files to work with in C++?C++ 'GET' 请求或如何下载文件以在 C++ 中使用?
【发布时间】:2009-01-07 06:00:54
【问题描述】:

好吧,我花了三天时间尝试这个,这是场景:

我想从 Google 下载一个“.csv”文件,然后对文件中的数据进行处理。它适用于 Win32 控制台应用程序。我有后者,我只是无法为我的生活弄清楚如何下载文件。我听说过 libcurl、curlpp、ptypes,我自己滚动,只是使用 .NET api,并且被告知了很多次:

...这只是一个 GET 请求

嗯,这一切都很好,但我一定错过了一些东西,因为似乎每个人都生来就知道如何做到这一点。我一直在梳理书籍以解决这个问题,甚至在与“C++ 的艺术”一起旅行了一段时间后,LNKerrors 出现了巨大的问题。

话虽如此,我从中学到了很多东西,但在这一点上,我只想知道如何去做。 C++ 的 API 严重缺乏,找不到示例代码。在线教程几乎不存在。似乎没有一本书认为这很重要。

有人可以给我扔一个救生筏吗?我是一个处于边缘的人。

编辑

“来自 Google”是指我想下载他们托管的 .csv 文件。一个例子可以是found here.

【问题讨论】:

    标签: .net c++ visual-c++ curl libcurl


    【解决方案1】:

    您应该可以根据自己的意愿bend this

    现在我已经回答了你的问题。为什么选择 C++?没有反对语言,但选择最适合工作的语言。 Perl、PHP 和 Python(我相信还有更多)都有很好的文档和对此类操作的支持。

    在 perl(我熟悉的那个)中只有大约 3-5 行代码。


    这里是代码 sn-p previously available in(来自WayBackMachine):

    /*
     * This is a very simple example of how to use libcurl from within 
     * a C++  program. The basic idea is that you want to retrieve the 
     * contents of a web page as a string. Obviously, you can replace 
     * the buffer object with anything you want and adjust elsewhere 
     * accordingly.
     * 
     * Hope you find it useful..
     * 
     * Todd Papaioannou
     */
    
    #include <string>
    #include <iostream>
    #include "curl/curl.h"
    
    using namespace std;
    
    // Write any errors in here
    static char errorBuffer[CURL_ERROR_SIZE];
    
    // Write all expected data in here
    static string buffer;
    
    // This is the writer call back function used by curl
    static int writer(char *data, size_t size, size_t nmemb,
                      std::string *buffer)
    {
      // What we will return
      int result = 0;
    
      // Is there anything in the buffer?
      if (buffer != NULL)
      {
        // Append the data to the buffer
        buffer->append(data, size * nmemb);
    
        // How much did we write?
        result = size * nmemb;
      }
    
      return result;
    }
    
    // You know what this does..
    void usage()
    {
      cout < < "curltest: \n" << endl;
      cout << "  Usage:  curltest url\n" << endl;
    } 
    
    /*
     * The old favorite
     */
    int main(int argc, char* argv[])
    {
      if (argc > 1) 
      {
        string url(argv[1]);
    
        cout < < "Retrieving " << url << endl;
    
        // Our curl objects
        CURL *curl;
        CURLcode result;
    
        // Create our curl handle
        curl = curl_easy_init();
    
        if (curl)
        {
          // Now set up all of the curl options
          curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
          curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
          curl_easy_setopt(curl, CURLOPT_HEADER, 0);
          curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
          curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
          curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
    
          // Attempt to retrieve the remote page
          result = curl_easy_perform(curl);
    
          // Always cleanup
          curl_easy_cleanup(curl);
    
          // Did we succeed?
          if (result == CURLE_OK)
          {
            cout << buffer << "\n";
            exit(0);
          }
          else
          {
            cout << "Error: [" << result << "] - " << errorBuffer;
            exit(-1);
          }
        }
      }
    }
    

    【讨论】:

    • 我认为答案是“然后对文件中的数据进行处理”。涉及另一个过程似乎很愚蠢,特别是如果这需要快速。
    • Jesse -- 用 libcurl 命令行多花 5 分钟下载文件,而不是花 3 天多时间根本没有得到文件,这似乎并不愚蠢!
    【解决方案2】:

    为什么不直接使用已有的?

    UrlDownloadToFile()

    【讨论】:

    • 我已经尝试过了,但遇到了很多问题,但从未真正下载过该文件。还有一点需要注意的是,如果您遇到“LPSCTWR”转换错误,请改用 URLDownloadToFileA(),因为 C++ 不喜欢您没有宽字符串。
    • 嗯 - 我从来没有遇到过使用 URLDownloadToFile() 的问题。通常,我做的很简单: URLDownloadToFileA(NULL, "url", "file", 0, NULL);那行得通。如果 IE 可以下载它(没有对话框提示),那么 UrlDownloadToFile() 应该可以工作。如果 IE 通过对话框提示某些内容,则必须实现
    • 实现 IBindStatusCallback、IAuthenticate 和 IHttpSecurity 的身份验证回调,然后将该回调作为最后一个参数传递给 UrlDownloadToFile()。
    【解决方案3】:

    由于您使用的是 Win32 平台,因此您可以使用一个内置库以相对直接的方式实现 GET 请求:WinInet,它是 Win32 SDK 的一部分。 basic reference for WinInet 可以在 MSDN 上找到。

    请注意,如果您不熟悉 Win32 API,将会遇到一些困难。有一个相当有用的示例代码块here

    如果您未能将适当的库引用添加到您的项目,您将收到链接器错误。听起来你已经在那里学到了一些教训,所以我会保持简短,但请放心,你会在 Win32 文档中找到所需的库和头文件引用的引用(你只需要了解在哪里要查找的页面)。

    【讨论】:

      【解决方案4】:

      标准库无法做到这一点。既然是win32,你可以听从Paul Keister的建议。

      但是看看libcurl,因为你使用的是C++,我推荐POCO,它也非常有用。它们是非常方便的工具!

      【讨论】:

      • 我不知道如何安装 libcurl。不过我会给 POCO 看看。
      【解决方案5】:

      另一个选项是WinHTTP,它也随 Windows 提供。

      【讨论】:

        【解决方案6】:

        >找不到示例代码

        ???

        已经发布了 15 年的数十个样本。 请参阅 api ng 新闻://comp.os.ms-windows.programmer.win32 (C 中的示例)

        (COM、INET 等)

        【讨论】:

          【解决方案7】:

          我也一直在为 C++ 寻找一个好的 http 库,但还没有找到“完美”的库。 Boost.Asio 非常棒,但对于一个简单的 http 库来说级别很低(尽管 http client examples 是一个好的开始)。 C++ Networking Library* (cpp-netlib) 看起来已经步入正轨,在 asio 之上构建更高级别的 api,但还不是很成熟。查看http_client example

          除非我能找到更好的选择,否则我要么编写自己的 asio 包装器,要么扩展(并贡献)到 cpp-netlib。

          (顺便说一句,libcurl 不是对我来说是一个更好的选择。它的 api 比我想要的要大得多,而且对于 http 客户端之类的东西非常笨拙,尤其是在 C++ 中。不要误会我的意思,这是一个很棒的库,但不适合简单的 http 客户端。)

          【讨论】:

            【解决方案8】:

            C++ 本身并没有真正的 API。要执行 GET 请求,您的程序需要打开与相关站点的 TCP 套接字连接,并将信息发送到套接字以符合 HTTP 规范,请参阅here。您可能可以找到许多库来帮助解决此问题,例如,您可以查看开源程序 wget 使用什么。如果您自己编写代码,那么使用数据包嗅探工具会很有帮助。您可以准确地看到您的浏览器发送到 Web 服务器以取回文件的内容,并准确地发送该消息。这不是太难,但它是相当难的。 TCP 最初是一个相当大的学习曲线。

            顺便问一下,“来自谷歌”是什么意思?

            【讨论】:

              猜你喜欢
              • 2021-05-21
              • 1970-01-01
              • 1970-01-01
              • 2023-04-02
              • 1970-01-01
              • 2010-10-23
              • 1970-01-01
              • 1970-01-01
              • 2010-10-30
              相关资源
              最近更新 更多