C++ [Libcurl] 从 php 服务器下载文件并将其保存在内存中

C++ [Libcurl] Downloading a file from a php server and save it on memory

你好,我正在尝试使用从我的 php 文件中检索到的 libcurl 下载文件,该文件会在检索下载文件之前检查用户是否已登录 c++ 客户端,问题是客户端永远不会到达下载文件以将其保存到内存中而不是将其写入磁盘我能做什么?我正在使用这个例子来测试。我还需要补充一点,我已经测试过无需登录就可以直接下载文件,一切都很好,但是登录大小永远为 0,而且我永远无法访问该文件。提前致谢。

    struct MemoryStruct {
  char *memory;
  size_t size;
};

static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)userp;

  char *ptr = realloc(mem->memory, mem->size + realsize + 1);
  if(ptr == NULL) {
    /* out of memory! */ 
    printf("not enough memory (realloc returned NULL)\n");
    return 0;
  }

  mem->memory = ptr;
  memcpy(&(mem->memory[mem->size]), contents, realsize);
  mem->size += realsize;
  mem->memory[mem->size] = 0;

  return realsize;
}

int main(void)
{
  CURL *curl_handle;
  CURLcode res;

  struct MemoryStruct chunk;

  chunk.memory = malloc(1);  /* will be grown as needed by the realloc above */ 
  chunk.size = 0;    /* no data at this point */ 

  curl_global_init(CURL_GLOBAL_ALL);

  /* init the curl session */ 
  curl_handle = curl_easy_init();

  /* specify URL to get */ 
  curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.example.com/");

  /* send all data to this function  */ 
  curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);

  /* we pass our 'chunk' struct to the callback function */ 
  curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);

  /* some servers don't like requests that are made without a user-agent
     field, so we provide one */ 
  curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");

  /* get it! */ 
  res = curl_easy_perform(curl_handle);

  /* check for errors */ 
  if(res != CURLE_OK) {
    fprintf(stderr, "curl_easy_perform() failed: %s\n",
            curl_easy_strerror(res));
  }
  else {
    /*
     * Now, our chunk.memory points to a memory block that is chunk.size
     * bytes big and contains the remote file.
     *
     * Do something nice with it!
     */ 

    printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
  }

  /* cleanup curl stuff */ 
  curl_easy_cleanup(curl_handle);

  free(chunk.memory);

  /* we're done with libcurl, so clean it up */ 
  curl_global_cleanup();

  return 0;
}

php代码是这样的

$path = '../file.dll';

                    if (file_exists($path))
                    {
                        $mm_type="application/octet-stream";
                        header("Pragma: public");
                        header("Expires: 0");
                        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
                        header("Cache-Control: public");
                        header("Content-Description: File Transfer");
                        header("Content-Type: " . $mm_type);
                        header("Content-Length: " .(string)(filesize($path)) );
                        header('Content-Disposition: attachment; filename="'.basename($path).'"');
                        header("Content-Transfer-Encoding: binary\n");
                        readfile($path);
                        }

很难从 php 片段中判断,但我会添加选项以遵循重定向并打开详细模式以便能够更详细地了解 libcurl 正在做什么。我还会删除所有手动内存管理。您所做的一切都可以用简单的 std::string 代替。

此示例适用于您发送的 php,但我无法测试您提到的登录内容:

#include <curl/curl.h>

#include <iostream>
#include <sstream>
#include <string>

static size_t WriteMemoryCallback(void* contents, size_t size, size_t nmemb,
                                  void* userp) {
    size_t realsize = size * nmemb;
    auto& mem = *static_cast<std::string*>(userp);
    mem.append(static_cast<char*>(contents), realsize);
    return realsize;
}

int main(void) {
    CURL* curl_handle;
    CURLcode res;

    std::string chunk;

    curl_global_init(CURL_GLOBAL_ALL);

    curl_handle = curl_easy_init();
    curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.example.com/");
    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &chunk);
    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");

    // added options that may be required
    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);  // redirects
    curl_easy_setopt(curl_handle, CURLOPT_HTTPPROXYTUNNEL, 1L); // corp. proxies etc.
    curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); // we want it all
    // curl_easy_setopt(curl_handle, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);

    res = curl_easy_perform(curl_handle);

    if(res != CURLE_OK) {
        std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << '\n';
    } else {
        std::cout << chunk.size() << " bytes retrieved\n";
    }

    curl_easy_cleanup(curl_handle);
    curl_global_cleanup();
}