在C / C ++中使用libcurl实施CURL命令

问题描述 投票:0回答:1

我正在使用的CURL命令如下所示。

curl -F 'file=@/home/karthik/Workspace/downloadfile.out' http://127.0.0.1:5000/file-upload --verbose

来自服务器的响应如下所示。

*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
> POST /file-upload HTTP/1.1
> Host: 127.0.0.1:5000
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Length: 663876790
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------4e96ef0714498bd7
> 
< HTTP/1.1 100 Continue
* HTTP 1.0, assume close after body
< HTTP/1.0 201 CREATED
< Content-Type: application/json
< Content-Length: 46
< Server: Werkzeug/0.16.0 Python/3.5.2
< Date: Sat, 14 Dec 2019 07:05:15 GMT
< 
{
  "message": "File successfully uploaded"
}
* Closing connection 0

我想使用libcurl在C / C ++中实现相同的命令。我正在使用以下功能。

int FileUploadDownload::upload(const std::string &filename, const std::string &url) {

    CURL *curl;
    CURLcode res;
    struct stat file_info;
    curl_off_t speed_upload, total_time;
    FILE *fd;

    fd = fopen(filename.c_str(), "rb");
    if(!fd) {
        m_logger->errorf("unable to open file: %s\n",strerror(errno));
        return 1;
    }
    if(fstat(fileno(fd), &file_info) != 0) {
        m_logger->errorf("unable to get file stats: %s\n",strerror(errno));
        return 2;
    }

    std::cout << "filename : "<< filename << std::endl;
    std::cout << "url : " << url << std::endl;

    curl = curl_easy_init();
    if(curl) {

        curl_easy_setopt(curl, CURLOPT_URL,
                         url.c_str());

        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, filename.c_str());
        curl_easy_setopt(curl, CURLOPT_POST, 1L);
        curl_easy_setopt(curl, CURLOPT_READDATA, fd);
        curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
                         (curl_off_t) file_info.st_size);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

        res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            m_logger->errorf("curl_easy_perform() failed: %s\n",curl_easy_strerror(res));
        } else {
            curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed_upload);
            curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time);
            m_logger->infof("Speed: %" CURL_FORMAT_CURL_OFF_T " bytes/sec during %"
                            CURL_FORMAT_CURL_OFF_T ".%06ld seconds\n",
                            speed_upload,
                            (total_time / 1000000), (long) (total_time % 1000000));
        }
    }
    return 0;
}

以下是我从服务器获得的结果。

The result that I get is shown below.
   *   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
> POST /file-upload HTTP/1.1
> Host: 127.0.0.1:5000
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Length: 550
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------c8ef4837136fca99
> 
< HTTP/1.1 100 Continue
* HTTP 1.0, assume close after body
< HTTP/1.0 201 CREATED
< Content-Type: application/json
< Content-Length: 46
< Server: Werkzeug/0.16.0 Python/3.5.2
< Date: Sat, 14 Dec 2019 07:09:47 GMT
< 
{
  "message": "File successfully uploaded"
}
* Closing connection 0

我的目标是在下面的C / C ++代码中模仿上面的curl命令。我在做什么错?

我在更新到最新的libcurl时遇到了一些困难。但是,我尝试如下手动设置HTTPHEADERS。

    stringstream ss;

    ss << "Content-Type:" << " multipart/form-data";
    list = curl_slist_append(list, ss.str().c_str());
    ss.str(std::string());

    ss << "filename=" << filename;
    list = curl_slist_append(list, ss.str().c_str());
    ss.str(std::string());

    ss << "name=file";
    list = curl_slist_append(list, ss.str().c_str());
    ss.str(std::string());

    ss << "Content-Type:" << " text/plain";
    list = curl_slist_append(list, ss.str().c_str());
    ss.str(std::string());

    ss << "Content-Disposition:" << " form-data";
    list = curl_slist_append(list, ss.str().c_str());

    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);

但是以下代码似乎无效。以上方法有效吗?如果是,我在做什么错?

c http curl post libcurl
1个回答
2
投票

要上传文件,您需要发送内容类型为multipart/form-data的数据。

为此,您需要创建表单并按以下格式附加文件数据。

#include <curl/curl.h>

#include <errno.h>
#include <iostream>
#include <stdio.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <string.h>

int upload(const std::string &filename, const std::string &url) {

  CURL *curl;
  CURLcode res;
  struct stat file_info;
  curl_off_t speed_upload, total_time;
  FILE *fd;

  curl_mime *form = NULL;
  curl_mimepart *field = NULL;
  struct curl_slist *headerlist = NULL;
  static const char buf[] = "Expect:";

  fd = fopen(filename.c_str(), "rb");
  if (!fd) {
    printf("unable to open file: %s\n", strerror(errno));
    return 1;
  }
  if (fstat(fileno(fd), &file_info) != 0) {
    printf("unable to get file stats: %s\n", strerror(errno));
    return 2;
  }

  std::cout << "filename : " << filename << ":"
            << std::endl;
  std::cout << "url : " << url << std::endl;

  curl = curl_easy_init();
  if (curl) {
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    form = curl_mime_init(curl);

    /* Fill in the file upload field */
    field = curl_mime_addpart(form);
    curl_mime_name(field, "file");
    curl_mime_filedata(field, filename.c_str());

    headerlist = curl_slist_append(headerlist, buf);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
    curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);

    res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
      printf("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
    } else {
      curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed_upload);
      curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time);
      printf("Speed: %" CURL_FORMAT_CURL_OFF_T
             " bytes/sec during %" CURL_FORMAT_CURL_OFF_T ".%06ld seconds\n",
             speed_upload, (total_time / 1000000),
             (long)(total_time % 1000000));
    }
  }
  return 0;
}

int main(int argc, char **argv) { return upload(argv[1], argv[2]); }

注意:

用法:./ a.out FileName ServerURL

© www.soinside.com 2019 - 2024. All rights reserved.