C ++ [Libcurl] Загрузка файла с сервера php и сохранение его в памяти - PullRequest
0 голосов
/ 09 апреля 2020

Здравствуйте, я пытаюсь загрузить файл с помощью libcurl, полученный из моего файла php, который проверяет, вошел ли пользователь на клиенте 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);
                        }

1 Ответ

0 голосов
/ 09 апреля 2020

Трудно сказать из этого фрагмента 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();
}
...