【问题标题】:formatting array of data into multipart/form-data将数据数组格式化为 multipart/form-data
【发布时间】:2021-11-03 12:06:10
【问题描述】:

我有一个代码,可以在其中接收数组中的加密数据。我正在努力使用 curl mime api 创建多部分/表单数据。任何人都可以帮助我/指导我如何创建多部分/表单数据。谢谢你。我是 curl 的新手,以前从未使用过 curl。我收到一条错误消息“无法从文件/应用程序打开/读取本地数据”。

#include <string>
#include <vector>
#include <iostream>
#include <curl/curl.h>
#include <curl/easy.h>

#define SYSLOG_INFO std::clog

struct Post {
    std::string url, chunk;
    static constexpr auto HeaderSize = 10;
    size_t static callBackFunk(char* buffer, size_t size, size_t nitmes,
                               void* userdata)
    { /*ignore?*/
        SYSLOG_INFO << __PRETTY_FUNCTION__ << "\n";
        return 0;
    }

    std::string libcurl(const std::vector<uint8_t>& cmdData)
    {
        CURL*              curl{nullptr};
        CURLcode           res;
        curl_mime*         form    = NULL;
        curl_mimepart*     field   = NULL;
        struct curl_slist* headers = NULL;
        static const char  buf[]   = "Expect:";

        std::string data = std::string(cmdData.begin(), cmdData.end());

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

        form  = curl_mime_init(curl);
        field = curl_mime_addpart(form);
        curl_mime_name(field, "upfile");
        curl_mime_filedata(field, data.c_str());

        field = curl_mime_addpart(form);
        curl_mime_name(field, "filename");
        curl_mime_filedata(field, data.c_str());

        std::string header =
            std::string(cmdData.begin(), cmdData.begin() + HeaderSize);
        SYSLOG_INFO << "header = " << header << std::endl;
        std::string headerAuth = "SCPv2: " + header;

        headers = curl_slist_append(headers, headerAuth.c_str());
        headers = curl_slist_append(headers, buf);

        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

        curl_easy_setopt(curl, CURLOPT_HEADERDATA, (std::string*)&chunk);
        curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, callBackFunk);

        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

        res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            std::cout << stderr << " curl_easy_perform() failed "
                      << curl_easy_strerror(res) << std::endl;
        }

        curl_easy_cleanup(curl);
        curl_mime_free(form);
        curl_slist_free_all(headers);

        return chunk;
    }
};

int main() {
    Post post {"http://www.example.com", "hello world"};

    post.libcurl({1,2,3,4});
}

命令

curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "cache-control:", CURLFORM_COPYCONTENTS, "no-cache", CURLFORM_END);

   curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "content-type:", CURLFORM_COPYCONTENTS, "multipart/form-data", CURLFORM_END);

   curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "file", CURLFORM_BUFFER, "data", CURLFORM_BUFFERPTR, cmdData.data(), CURLFORM_BUFFERLENGTH, cmdData.size(), CURLFORM_END);

【问题讨论】:

  • mcve 请。不清楚cmdData里面是什么,或者payload是什么等等……
  • 对不起,我更新了代码。
  • 不,这个例子甚至不能编译
  • @pptaszni 为您自成一体

标签: c++ curl https multipartform-data libcurl


【解决方案1】:

使用 curl_mime_filedata() 函数,curl 将尝试从名为 data.c_str() 的文件路径中加载内容,如果找不到该文件,curl 会显示上面的错误消息。如果你想上传数据内容,你应该使用 curl_mime_data() 代替:

filename 指向以 null 结尾的文件的路径名。指针 可以为 NULL 以分离以前的部分内容设置。文件名 调用后可以安全地重复使用存储空间。

...

文件的内容在文件传输过程中被读取 流式传输方式以允许在不使用的情况下传输大文件 很多内存。因此,它要求文件在 整个请求。

上传名为“example.dat”且内容由数据字符串设置的文件的代码应为(修改自curl示例here):

  CURL *curl;
  CURLM *multi_handle;

  int still_running = 0;
  curl_mime *form = NULL;
  curl_mimepart *field = NULL;
  struct curl_slist *headerlist = NULL;

  std::string data = {"1234"};

  //... add your headers definition ....

  curl = curl_easy_init();
  multi_handle = curl_multi_init();

  if(curl && multi_handle) {

    /* Create the form */
    form = curl_mime_init(curl);

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

    /* Fill in the filename field */
    field = curl_mime_addpart(form);
    curl_mime_name(field, "filename");
    curl_mime_data(field, "example.dat", CURL_ZERO_TERMINATED);

    //... set your headers here ...

    /* what URL that receives this POST */
    curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
    curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
    curl_multi_add_handle(multi_handle, curl);
    do {
      CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
      if(still_running)
        /* wait for activity, timeout or "nothing" */
        mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
      if(mc)
        break;
    } while(still_running);
    curl_multi_cleanup(multi_handle);
    /* always cleanup */
    curl_easy_cleanup(curl);
    /* then cleanup the form */
    curl_mime_free(form);
    /* free slist */
    curl_slist_free_all(headerlist);
  }

如果程序出错,则表示服务器端不接受“upfile”或“filename”变量。您应该检查服务器端部分以获取更多信息。

上面显示的代码与以下 curl 命令相同:

curl -F 'upfile=1234' -F 'filename=example.dat' http://www.example.com

【讨论】:

  • 它不起作用,我从服务器收到 400 错误请求。
  • 我在上面的问题中添加了formadd函数。现在我收到 500 内部服务器错误。请求标头是正确的,但我仍然不明白为什么它会显示错误。
  • 非常感谢。
猜你喜欢
  • 2012-11-10
  • 2021-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-31
  • 2017-08-04
  • 1970-01-01
  • 2012-10-01
相关资源
最近更新 更多